diff --git a/Doc/library/multiprocessing.shared_memory.rst b/Doc/library/multiprocessing.shared_memory.rst
index e8f04a6ac7b95d..334d515503653a 100644
--- a/Doc/library/multiprocessing.shared_memory.rst
+++ b/Doc/library/multiprocessing.shared_memory.rst
@@ -112,6 +112,32 @@ copying of data.
       This method has no effect on Windows, where the only way to delete a
       shared memory block is to close all handles.
 
+   .. method:: rename(newname, flags=0)
+
+      Rename the underlying shared memory block to *newname*.
+      By default, if *newname* already exists, it will be unlinked beforehand.
+
+      *flags* (0 by default) takes :ref:`bitwise ORed <bitwise>` flags together.
+
+   .. availability:: FreeBSD >= 13.0
+
+   .. versionadded:: next
+
+   .. data:: SHM_RENAME_EXCHANGE
+             SHM_RENAME_NOREPLACE
+
+      Parameters to the :func:`rename` function.
+
+      :const:`SHM_RENAME_EXCHANGE`
+        Atomically exchange the SharedMemory to the *newname*.
+
+      :const:`SHM_RENAME_NOREPLACE`
+        Raise an error if *newname* exists, rather than unlinking it.
+
+   .. availability:: FreeBSD >= 13.0
+
+   .. versionadded:: next
+
    .. attribute:: buf
 
       A memoryview of contents of the shared memory block.
diff --git a/Lib/multiprocessing/shared_memory.py b/Lib/multiprocessing/shared_memory.py
index 99a8ce3320ad4e..690e27aaeeef0d 100644
--- a/Lib/multiprocessing/shared_memory.py
+++ b/Lib/multiprocessing/shared_memory.py
@@ -11,6 +11,7 @@
 from functools import partial
 import mmap
 import os
+import platform
 import errno
 import struct
 import secrets
@@ -36,6 +37,10 @@
 else:
     _SHM_NAME_PREFIX = 'wnsm_'
 
+if _USE_POSIX and hasattr(_posixshmem, "shm_rename"):
+    from _posixshmem import SHM_RENAME_EXCHANGE
+    from _posixshmem import SHM_RENAME_NOREPLACE
+
 
 def _make_filename():
     "Create a random filename for the shared memory object."
@@ -253,6 +258,27 @@ def unlink(self):
             if self._track:
                 resource_tracker.unregister(self._name, "shared_memory")
 
+    if _USE_POSIX and hasattr(_posixshmem, "shm_rename"):
+        def rename(self, newname, flags=0):
+            """Renames a shared memory block.
+
+            The policy how the operation is handled depends on the flag passed.
+            The default behavior is if the newname already exists, it will
+            be unlinked beforehand.
+            With the SHM_RENAME_EXCHANGE flag, the old and new name will
+            be exchanged.
+            With the SHM_RENAME_NOREPLACE flag, an error will be returned
+            if the new name exists.
+            """
+            oldname = self._name
+            if _USE_POSIX and self._prepend_leading_slash:
+                newname = "/" + newname
+            self._fd = _posixshmem.shm_rename(self._name, newname, flags)
+            if self._track:
+                resource_tracker.unregister(oldname, "shared_memory")
+                resource_tracker.register(newname, "shared_memory")
+            self._name = newname
+
 
 _encoding = "utf8"
 
diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py
index dcce57629efe5b..fd39dd9614812e 100644
--- a/Lib/test/_test_multiprocessing.py
+++ b/Lib/test/_test_multiprocessing.py
@@ -4376,6 +4376,41 @@ def test_shared_memory_recreate(self):
             self.addCleanup(shm2.unlink)
             self.assertEqual(shm2._name, names[1])
 
+    @unittest.skipUnless(hasattr(shared_memory.SharedMemory, "rename"),
+                         "requires SharedMomery.rename")
+    def test_shared_memory_rename(self):
+        name1 = self._new_shm_name('testrename01_tsmb')
+        name2 = self._new_shm_name('testrename02_tsmb')
+        sms = shared_memory.SharedMemory(name1, create=True, size=512)
+        self.addCleanup(sms.unlink)
+
+        sms.rename(name2)
+        self.assertEqual(sms.name, name2)
+
+    @unittest.skipUnless(hasattr(shared_memory.SharedMemory, "rename"),
+                         "requires SharedMomery.rename")
+    def test_shared_memory_rename_noreplace(self):
+        name1 = self._new_shm_name('testrename01_tsmb')
+        name2 = self._new_shm_name('testrename02_tsmb')
+        sms1 = shared_memory.SharedMemory(name1, create=True, size=512)
+        sms2 = shared_memory.SharedMemory(name2, create=True, size=512)
+        self.addCleanup(sms1.unlink)
+        self.addCleanup(sms2.unlink)
+
+        with self.assertRaises(FileExistsError):
+            sms1.rename(name2, flags=shared_memory.SHM_RENAME_NOREPLACE)
+
+    @unittest.skipUnless(hasattr(shared_memory.SharedMemory, "rename"),
+                         "requires SharedMomery.rename")
+    def test_shared_memory_rename_exchange(self):
+        name1 = self._new_shm_name('testrename01_tsmb')
+        name2 = self._new_shm_name('testrename02_tsmb')
+        sms1 = shared_memory.SharedMemory(name1, create=True, size=512)
+        sms2 = shared_memory.SharedMemory(name2, create=True, size=512)
+        self.addCleanup(sms2.unlink)
+
+        sms1.rename(name2, flags=shared_memory.SHM_RENAME_EXCHANGE)
+
     def test_invalid_shared_memory_creation(self):
         # Test creating a shared memory segment with negative size
         with self.assertRaises(ValueError):
diff --git a/Misc/NEWS.d/next/Library/2022-01-17-20-03-56.bpo-46398.FATeqM.rst b/Misc/NEWS.d/next/Library/2022-01-17-20-03-56.bpo-46398.FATeqM.rst
new file mode 100644
index 00000000000000..d253aaf8ab35d8
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-01-17-20-03-56.bpo-46398.FATeqM.rst
@@ -0,0 +1 @@
+Add the :mod:`multiprocessing.shared_memory.SharedMemory.rename` method for FreeBSD.
diff --git a/Modules/_multiprocessing/clinic/posixshmem.c.h b/Modules/_multiprocessing/clinic/posixshmem.c.h
index a545ff4d80f067..e9109a3c2b8ba8 100644
--- a/Modules/_multiprocessing/clinic/posixshmem.c.h
+++ b/Modules/_multiprocessing/clinic/posixshmem.c.h
@@ -42,6 +42,67 @@ _posixshmem_shm_open(PyObject *module, PyObject *args, PyObject *kwargs)
 
 #endif /* defined(HAVE_SHM_OPEN) */
 
+#if defined(HAVE_SHM_RENAME)
+
+PyDoc_STRVAR(_posixshmem_shm_rename__doc__,
+"shm_rename($module, path_from, path_to, flags, /)\n"
+"--\n"
+"\n"
+"Rename a shared memory object.\n"
+"\n"
+"Remove a shared memory object and relink to another path.\n"
+"By default, if the destination path already exist, it will be unlinked.\n"
+"With the SHM_RENAME_EXCHANGE flag, source and destination paths\n"
+"will be exchanged.\n"
+"With the SHM_RENAME_NOREPLACE flag, an error will be triggered\n"
+"if the destination alredady exists.");
+
+#define _POSIXSHMEM_SHM_RENAME_METHODDEF    \
+    {"shm_rename", (PyCFunction)(void(*)(void))_posixshmem_shm_rename, METH_FASTCALL, _posixshmem_shm_rename__doc__},
+
+static int
+_posixshmem_shm_rename_impl(PyObject *module, PyObject *path_from,
+                            PyObject *path_to, int flags);
+
+static PyObject *
+_posixshmem_shm_rename(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *path_from;
+    PyObject *path_to;
+    int flags;
+    int _return_value;
+
+    if (nargs != 3) {
+        PyErr_Format(PyExc_TypeError, "shm_rename expected 3 arguments, got %zd", nargs);
+        goto exit;
+    }
+    if (!PyUnicode_Check(args[0])) {
+        PyErr_Format(PyExc_TypeError, "shm_rename() argument 1 must be str, not %T", args[0]);
+        goto exit;
+    }
+    path_from = args[0];
+    if (!PyUnicode_Check(args[1])) {
+        PyErr_Format(PyExc_TypeError, "shm_rename() argument 2 must be str, not %T", args[1]);
+        goto exit;
+    }
+    path_to = args[1];
+    flags = PyLong_AsInt(args[2]);
+    if (flags == -1 && PyErr_Occurred()) {
+        goto exit;
+    }
+    _return_value = _posixshmem_shm_rename_impl(module, path_from, path_to, flags);
+    if ((_return_value == -1) && PyErr_Occurred()) {
+        goto exit;
+    }
+    return_value = PyLong_FromLong((long)_return_value);
+
+exit:
+    return return_value;
+}
+
+#endif /* defined(HAVE_SHM_RENAME) */
+
 #if defined(HAVE_SHM_UNLINK)
 
 PyDoc_STRVAR(_posixshmem_shm_unlink__doc__,
@@ -83,7 +144,11 @@ _posixshmem_shm_unlink(PyObject *module, PyObject *arg)
     #define _POSIXSHMEM_SHM_OPEN_METHODDEF
 #endif /* !defined(_POSIXSHMEM_SHM_OPEN_METHODDEF) */
 
+#ifndef _POSIXSHMEM_SHM_RENAME_METHODDEF
+    #define _POSIXSHMEM_SHM_RENAME_METHODDEF
+#endif /* !defined(_POSIXSHMEM_SHM_RENAME_METHODDEF) */
+
 #ifndef _POSIXSHMEM_SHM_UNLINK_METHODDEF
     #define _POSIXSHMEM_SHM_UNLINK_METHODDEF
 #endif /* !defined(_POSIXSHMEM_SHM_UNLINK_METHODDEF) */
-/*[clinic end generated code: output=74588a5abba6e36c input=a9049054013a1b77]*/
+/*[clinic end generated code: output=3b3a888f3ea27db0 input=a9049054013a1b77]*/
diff --git a/Modules/_multiprocessing/posixshmem.c b/Modules/_multiprocessing/posixshmem.c
index ab45e4136c7d46..55e762cd58683c 100644
--- a/Modules/_multiprocessing/posixshmem.c
+++ b/Modules/_multiprocessing/posixshmem.c
@@ -73,6 +73,59 @@ _posixshmem_shm_open_impl(PyObject *module, PyObject *path, int flags,
 }
 #endif /* HAVE_SHM_OPEN */
 
+#ifdef HAVE_SHM_RENAME
+/*[clinic input]
+_posixshmem.shm_rename -> int
+    path_from: unicode
+    path_to: unicode
+    flags: int
+    /
+
+Rename a shared memory object.
+
+Remove a shared memory object and relink to another path.
+By default, if the destination path already exist, it will be unlinked.
+With the SHM_RENAME_EXCHANGE flag, source and destination paths
+will be exchanged.
+With the SHM_RENAME_NOREPLACE flag, an error will be triggered
+if the destination alredady exists.
+
+[clinic start generated code]*/
+
+static int
+_posixshmem_shm_rename_impl(PyObject *module, PyObject *path_from,
+                            PyObject *path_to, int flags)
+/*[clinic end generated code: output=d9a710c512166e18 input=5fb42d1ce077caec]*/
+{
+    int rv;
+    int async_err = 0;
+    Py_ssize_t from_size;
+    Py_ssize_t to_size;
+    const char *from = PyUnicode_AsUTF8AndSize(path_from, &from_size);
+    const char *to = PyUnicode_AsUTF8AndSize(path_to, &to_size);
+    if (from == NULL || to == NULL) {
+        return -1;
+    }
+    if (strlen(from) != (size_t)from_size || strlen(to) != (size_t)to_size) {
+        PyErr_SetString(PyExc_ValueError, "embedded null character");
+        return -1;
+    }
+    do {
+        Py_BEGIN_ALLOW_THREADS
+        rv = shm_rename(from, to, flags);
+        Py_END_ALLOW_THREADS
+    } while (rv < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+
+    if (rv < 0) {
+        if (!async_err)
+            PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path_from, path_to);
+        return -1;
+    }
+
+    return rv;
+}
+#endif /* HAVE_SHM_RENAME */
+
 #ifdef HAVE_SHM_UNLINK
 /*[clinic input]
 _posixshmem.shm_unlink
@@ -122,12 +175,29 @@ _posixshmem_shm_unlink_impl(PyObject *module, PyObject *path)
 
 static PyMethodDef module_methods[ ] = {
     _POSIXSHMEM_SHM_OPEN_METHODDEF
+#if defined(HAVE_SHM_RENAME)
+    _POSIXSHMEM_SHM_RENAME_METHODDEF
+#endif
     _POSIXSHMEM_SHM_UNLINK_METHODDEF
     {NULL} /* Sentinel */
 };
 
+static int
+posixshmem_exec(PyObject *m)
+{
+#ifdef HAVE_SHM_RENAME
+#ifdef SHM_RENAME_EXCHANGE
+    if (PyModule_AddIntMacro(m, SHM_RENAME_EXCHANGE)) return -1;
+#endif
+#ifdef SHM_RENAME_NOREPLACE
+    if (PyModule_AddIntMacro(m, SHM_RENAME_NOREPLACE)) return -1;
+#endif
+#endif /* HAVE_SHM_RENAME */
+    return 0;
+}
 
 static PyModuleDef_Slot module_slots[] = {
+    {Py_mod_exec, posixshmem_exec},
     {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
     {Py_mod_gil, Py_MOD_GIL_NOT_USED},
     {0, NULL}
diff --git a/configure b/configure
index 1b75ddfa26dcdd..06b24bd594d3f4 100755
--- a/configure
+++ b/configure
@@ -29813,7 +29813,7 @@ fi
   #endif
   "
 
-  for ac_func in shm_open shm_unlink
+  for ac_func in shm_open shm_rename shm_unlink
 do :
   as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | sed "$as_sed_sh"`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/configure.ac b/configure.ac
index c449bb5ebb3cd4..4c77b93cdd48d6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7297,7 +7297,7 @@ WITH_SAVE_ENV([
   #  endif
   #endif
   "
-  AC_CHECK_FUNCS([shm_open shm_unlink], [have_posix_shmem=yes], [have_posix_shmem=no])
+  AC_CHECK_FUNCS([shm_open shm_rename shm_unlink], [have_posix_shmem=yes], [have_posix_shmem=no])
   _RESTORE_VAR([ac_includes_default])
 ])
 
diff --git a/pyconfig.h.in b/pyconfig.h.in
index aa086d49e90a5b..a7fe8b59511591 100644
--- a/pyconfig.h.in
+++ b/pyconfig.h.in
@@ -1191,6 +1191,9 @@
 /* Define to 1 if you have the 'shm_open' function. */
 #undef HAVE_SHM_OPEN
 
+/* Define to 1 if you have the 'shm_rename' function. */
+#undef HAVE_SHM_RENAME
+
 /* Define to 1 if you have the 'shm_unlink' function. */
 #undef HAVE_SHM_UNLINK