async_posix.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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. /* This must be the first #include file */
  10. #include "../async_local.h"
  11. #ifdef ASYNC_POSIX
  12. # include <stddef.h>
  13. # include <unistd.h>
  14. # include <openssl/err.h>
  15. # include <openssl/crypto.h>
  16. #define STACKSIZE 32768
  17. static CRYPTO_RWLOCK *async_mem_lock;
  18. static void *async_stack_alloc(size_t *num);
  19. static void async_stack_free(void *addr);
  20. int async_local_init(void)
  21. {
  22. async_mem_lock = CRYPTO_THREAD_lock_new();
  23. return async_mem_lock != NULL;
  24. }
  25. void async_local_deinit(void)
  26. {
  27. CRYPTO_THREAD_lock_free(async_mem_lock);
  28. }
  29. static int allow_customize = 1;
  30. static ASYNC_stack_alloc_fn stack_alloc_impl = async_stack_alloc;
  31. static ASYNC_stack_free_fn stack_free_impl = async_stack_free;
  32. int ASYNC_is_capable(void)
  33. {
  34. ucontext_t ctx;
  35. /*
  36. * Some platforms provide getcontext() but it does not work (notably
  37. * MacOSX PPC64). Check for a working getcontext();
  38. */
  39. return getcontext(&ctx) == 0;
  40. }
  41. int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn,
  42. ASYNC_stack_free_fn free_fn)
  43. {
  44. OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL);
  45. if (!CRYPTO_THREAD_write_lock(async_mem_lock))
  46. return 0;
  47. if (!allow_customize) {
  48. CRYPTO_THREAD_unlock(async_mem_lock);
  49. return 0;
  50. }
  51. CRYPTO_THREAD_unlock(async_mem_lock);
  52. if (alloc_fn != NULL)
  53. stack_alloc_impl = alloc_fn;
  54. if (free_fn != NULL)
  55. stack_free_impl = free_fn;
  56. return 1;
  57. }
  58. void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn *alloc_fn,
  59. ASYNC_stack_free_fn *free_fn)
  60. {
  61. if (alloc_fn != NULL)
  62. *alloc_fn = stack_alloc_impl;
  63. if (free_fn != NULL)
  64. *free_fn = stack_free_impl;
  65. }
  66. static void *async_stack_alloc(size_t *num)
  67. {
  68. return OPENSSL_malloc(*num);
  69. }
  70. static void async_stack_free(void *addr)
  71. {
  72. OPENSSL_free(addr);
  73. }
  74. void async_local_cleanup(void)
  75. {
  76. }
  77. int async_fibre_makecontext(async_fibre *fibre)
  78. {
  79. #ifndef USE_SWAPCONTEXT
  80. fibre->env_init = 0;
  81. #endif
  82. if (getcontext(&fibre->fibre) == 0) {
  83. size_t num = STACKSIZE;
  84. /*
  85. * Disallow customisation after the first
  86. * stack is allocated.
  87. */
  88. if (allow_customize) {
  89. if (!CRYPTO_THREAD_write_lock(async_mem_lock))
  90. return 0;
  91. allow_customize = 0;
  92. CRYPTO_THREAD_unlock(async_mem_lock);
  93. }
  94. fibre->fibre.uc_stack.ss_sp = stack_alloc_impl(&num);
  95. if (fibre->fibre.uc_stack.ss_sp != NULL) {
  96. fibre->fibre.uc_stack.ss_size = num;
  97. fibre->fibre.uc_link = NULL;
  98. makecontext(&fibre->fibre, async_start_func, 0);
  99. return 1;
  100. }
  101. } else {
  102. fibre->fibre.uc_stack.ss_sp = NULL;
  103. }
  104. return 0;
  105. }
  106. void async_fibre_free(async_fibre *fibre)
  107. {
  108. stack_free_impl(fibre->fibre.uc_stack.ss_sp);
  109. fibre->fibre.uc_stack.ss_sp = NULL;
  110. }
  111. #endif