---
name: "pmem_memmove_persist"
section: "3"
platform: "linux"
package: "libpmem-dev"
version: "1.13.1-1.1+b1"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/pmem_memmove_persist"
---

# pmem\_memmove\_persist(3)

functions that provide optimized copying to persistent memory

## NAME

**pmem\_memmove**(), **pmem\_memcpy**(), **pmem\_memset**(), **pmem\_memmove\_persist**(), **pmem\_memcpy\_persist**(), **pmem\_memset\_persist**(), **pmem\_memmove\_nodrain**(), **pmem\_memcpy\_nodrain**(), **pmem\_memset\_nodrain**() - functions that provide optimized copying to persistent memory

## SYNOPSIS

-

  ```
  #include <libpmem.h>
  void *pmem_memmove(void *pmemdest, const void *src, size_t len, unsigned flags);
  void *pmem_memcpy(void *pmemdest, const void *src, size_t len, unsigned flags);
  void *pmem_memset(void *pmemdest, int c, size_t len, unsigned flags);
  void *pmem_memmove_persist(void *pmemdest, const void *src, size_t len);
  void *pmem_memcpy_persist(void *pmemdest, const void *src, size_t len);
  void *pmem_memset_persist(void *pmemdest, int c, size_t len);
  void *pmem_memmove_nodrain(void *pmemdest, const void *src, size_t len);
  void *pmem_memcpy_nodrain(void *pmemdest, const void *src, size_t len);
  void *pmem_memset_nodrain(void *pmemdest, int c, size_t len);
  ```

## DESCRIPTION

**pmem\_memmove**(), **pmem\_memcpy**() and **pmem\_memset**() functions provide the same memory copying as their namesakes [**memmove**(3)](/memmove/3.md), [**memcpy**(3)](/memcpy/3.md) and [**memset**(3)](/memset/3.md), and ensure that the result has been flushed to persistence before returning (unless **PMEM\_F\_MEM\_NOFLUSH** flag was used).

For example, the following code is functionally equivalent to **pmem\_memmove**() (with flags equal to 0):

-

  ```
      memmove(dest, src, len);
      pmem_persist(dest, len);
  ```

Calling **pmem\_memmove**() may out-perform the above code, because [**libpmem**(7)](/libpmem/7.md) implementation may take advantage of the fact that *pmemdest* is persistent memory and use instructions such as *non-temporal* stores to avoid the need to flush processor caches.

WARNING: Using these functions where [**pmem\_is\_pmem**(3)](/pmem_is_pmem/3.md) returns false may not do anything useful. Use libc functions in that case.

Unlike libc implementation, **libpmem** functions guarantee that if destination buffer address and length are 8 byte aligned then all stores will be performed using at least 8 byte store instructions. This means that a series of 8 byte stores followed by [**pmem\_persist**(3)](/pmem_persist/3.md) can be safely replaced by a single call to one of the above functions.

The *flags* argument of all of the above functions has the same meaning. It can be 0 or a bitwise OR of one or more of the following flags:

- •

  **PMEM\_F\_MEM\_NODRAIN** - modifies the behavior to skip the final **pmem\_drain**() step. This allows applications to optimize cases where several ranges are being copied to persistent memory, followed by a single call to **pmem\_drain**(). The following example illustrates how this flag might be used to avoid multiple calls to **pmem\_drain**() when copying several ranges of memory to pmem:

-

  ```
  /* ... write several ranges to pmem ... */
  pmem_memcpy(pmemdest1, src1, len1, PMEM_F_MEM_NODRAIN);
  pmem_memcpy(pmemdest2, src2, len2, PMEM_F_MEM_NODRAIN);
  /* ... */
  /* wait for any pmem stores to drain from HW buffers */
  pmem_drain();
  ```

- •

  **PMEM\_F\_MEM\_NOFLUSH** - Don’t flush anything. This implies **PMEM\_F\_MEM\_NODRAIN**. Using this flag only makes sense when it’s followed by any function that flushes data.

The remaining flags say *how* the operation should be done, and are merely hints.

- •

  **PMEM\_F\_MEM\_NONTEMPORAL** - Use non-temporal instructions. This flag is mutually exclusive with **PMEM\_F\_MEM\_TEMPORAL**. On x86\_64 this flag is mutually exclusive with **PMEM\_F\_MEM\_NOFLUSH**.

- •

  **PMEM\_F\_MEM\_TEMPORAL** - Use temporal instructions. This flag is mutually exclusive with **PMEM\_F\_MEM\_NONTEMPORAL**.

- •

  **PMEM\_F\_MEM\_WC** - Use write combining mode. This flag is mutually exclusive with **PMEM\_F\_MEM\_WB**. On x86\_64 this flag is mutually exclusive with **PMEM\_F\_MEM\_NOFLUSH**.

- •

  **PMEM\_F\_MEM\_WB** - Use write back mode. This flag is mutually exclusive with **PMEM\_F\_MEM\_WC**. On x86\_64 this is an alias for **PMEM\_F\_MEM\_TEMPORAL**.

Using an invalid combination of flags has undefined behavior.

Without any of the above flags **libpmem** will try to guess the best strategy based on size. See **PMEM\_MOVNT\_THRESHOLD** description in [**libpmem**(7)](/libpmem/7.md) for details.

**pmem\_memmove\_persist**() is an alias for **pmem\_memmove**() with flags equal to 0.

**pmem\_memcpy\_persist**() is an alias for **pmem\_memcpy**() with flags equal to 0.

**pmem\_memset\_persist**() is an alias for **pmem\_memset**() with flags equal to 0.

**pmem\_memmove\_nodrain**() is an alias for **pmem\_memmove**() with flags equal to **PMEM\_F\_MEM\_NODRAIN**.

**pmem\_memcpy\_nodrain**() is an alias for **pmem\_memcpy**() with flags equal to **PMEM\_F\_MEM\_NODRAIN**.

**pmem\_memset\_nodrain**() is an alias for **pmem\_memset**() with flags equal to **PMEM\_F\_MEM\_NODRAIN**.

## RETURN VALUE

All of the above functions return address of the destination buffer.

## CAVEATS

After calling any of the functions with **PMEM\_F\_MEM\_NODRAIN** flag you should not expect memory to be visible to other threads before calling [**pmem\_drain**(3)](/pmem_drain/3.md) or any of the *\_persist* functions. This is because on x86\_64 those functions may use non-temporal store instructions, which are weakly ordered. See “Intel 64 and IA-32 Architectures Software Developer’s Manual”, Volume 1, “Caching of Temporal vs. Non-Temporal Data” section for details.

## SEE ALSO

[**memcpy**(3)](/memcpy/3.md), [**memmove**(3)](/memmove/3.md), [**memset**(3)](/memset/3.md), [**libpmem**(7)](/libpmem/7.md) and **\<https://pmem.io\>**
