mlock.py 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. # -*- coding: utf-8 -*-
  2. """
  3. # mlock support
  4. # Copyright (c) 2019-2023 Michael Büsch <m@bues.ch>
  5. # Licensed under the GNU/GPL version 2 or later.
  6. """
  7. import platform
  8. import os
  9. import sys
  10. __all__ = [
  11. "MLockWrapper",
  12. ]
  13. class MLockWrapper:
  14. """OS mlock wrapper.
  15. """
  16. singleton = None
  17. def __init__(self):
  18. self.__ffi = None
  19. self.__libc = None
  20. if os.name != "posix" or "linux" not in sys.platform.lower():
  21. return # "mlock() is only supported on Linux.
  22. try:
  23. from cffi import FFI
  24. except ImportError as e:
  25. print("Failed to import CFFI: %s\n"
  26. "Cannot use mlock() via CFFI.\n"
  27. "You might want to install CFFI by running: "
  28. "pip3 install cffi" % (
  29. str(e)), file=sys.stderr)
  30. return
  31. self.__ffi = FFI()
  32. # Use getattr to avoid Cython cdef compile error.
  33. getattr(self.__ffi, "cdef")("int mlockall(int flags);")
  34. self.__libc = self.__ffi.dlopen(None)
  35. @classmethod
  36. def get(cls):
  37. s = cls.singleton
  38. if not s:
  39. s = cls.singleton = cls()
  40. return s
  41. @classmethod
  42. def mlockall(cls):
  43. """Lock all current and all future memory.
  44. """
  45. error = "mlockall() is not supported on this operating system."
  46. s = cls.get()
  47. if s.__libc:
  48. if platform.machine().lower() in (
  49. "alpha",
  50. "ppc", "ppc64", "ppcle", "ppc64le",
  51. "sparc", "sparc64" ):
  52. MCL_CURRENT = 0x2000
  53. MCL_FUTURE = 0x4000
  54. else:
  55. MCL_CURRENT = 0x1
  56. MCL_FUTURE = 0x2
  57. ret = s.__libc.mlockall(MCL_CURRENT | MCL_FUTURE)
  58. error = os.strerror(s.__ffi.errno) if ret else ""
  59. return error