async_posix.h 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /*
  2. * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #ifndef OSSL_CRYPTO_ASYNC_POSIX_H
  10. #define OSSL_CRYPTO_ASYNC_POSIX_H
  11. #include <openssl/e_os2.h>
  12. #if defined(OPENSSL_SYS_UNIX) \
  13. && defined(OPENSSL_THREADS) && !defined(OPENSSL_NO_ASYNC) \
  14. && !defined(__ANDROID__) && !defined(__OpenBSD__)
  15. # include <unistd.h>
  16. # if _POSIX_VERSION >= 200112L \
  17. && (_POSIX_VERSION < 200809L || defined(__GLIBC__))
  18. # include <pthread.h>
  19. # define ASYNC_POSIX
  20. # define ASYNC_ARCH
  21. # if defined(__CET__) || defined(__ia64__)
  22. /*
  23. * When Intel CET is enabled, makecontext will create a different
  24. * shadow stack for each context. async_fibre_swapcontext cannot
  25. * use _longjmp. It must call swapcontext to swap shadow stack as
  26. * well as normal stack.
  27. * On IA64 the register stack engine is not saved across setjmp/longjmp. Here
  28. * swapcontext() performs correctly.
  29. */
  30. # define USE_SWAPCONTEXT
  31. # endif
  32. # if defined(__aarch64__) && defined(__clang__) \
  33. && defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT == 1
  34. /*
  35. * setjmp/longjmp don't currently work with BTI on all libc implementations
  36. * when compiled by clang. This is because clang doesn't put a BTI after the
  37. * call to setjmp where it returns the second time. This then fails on libc
  38. * implementations - notably glibc - which use an indirect jump to there.
  39. * So use the swapcontext implementation, which does work.
  40. * See https://github.com/llvm/llvm-project/issues/48888.
  41. */
  42. # define USE_SWAPCONTEXT
  43. # endif
  44. # include <ucontext.h>
  45. # ifndef USE_SWAPCONTEXT
  46. # include <setjmp.h>
  47. # endif
  48. typedef struct async_fibre_st {
  49. ucontext_t fibre;
  50. # ifndef USE_SWAPCONTEXT
  51. jmp_buf env;
  52. int env_init;
  53. # endif
  54. } async_fibre;
  55. int async_local_init(void);
  56. void async_local_deinit(void);
  57. static ossl_inline int async_fibre_swapcontext(async_fibre *o, async_fibre *n, int r)
  58. {
  59. # ifdef USE_SWAPCONTEXT
  60. swapcontext(&o->fibre, &n->fibre);
  61. # else
  62. o->env_init = 1;
  63. if (!r || !_setjmp(o->env)) {
  64. if (n->env_init)
  65. _longjmp(n->env, 1);
  66. else
  67. setcontext(&n->fibre);
  68. }
  69. # endif
  70. return 1;
  71. }
  72. # define async_fibre_init_dispatcher(d)
  73. int async_fibre_makecontext(async_fibre *fibre);
  74. void async_fibre_free(async_fibre *fibre);
  75. # endif
  76. #endif
  77. #endif /* OSSL_CRYPTO_ASYNC_POSIX_H */