async_posix.h 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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. static ossl_inline int async_fibre_swapcontext(async_fibre *o, async_fibre *n, int r)
  56. {
  57. # ifdef USE_SWAPCONTEXT
  58. swapcontext(&o->fibre, &n->fibre);
  59. # else
  60. o->env_init = 1;
  61. if (!r || !_setjmp(o->env)) {
  62. if (n->env_init)
  63. _longjmp(n->env, 1);
  64. else
  65. setcontext(&n->fibre);
  66. }
  67. # endif
  68. return 1;
  69. }
  70. # define async_fibre_init_dispatcher(d)
  71. int async_fibre_makecontext(async_fibre *fibre);
  72. void async_fibre_free(async_fibre *fibre);
  73. # endif
  74. #endif
  75. #endif /* OSSL_CRYPTO_ASYNC_POSIX_H */