iodine 0.7.44 → 0.7.47

Sign up to get free protection for your applications and to get access to all the features.
data/ext/iodine/fio.h CHANGED
@@ -215,8 +215,15 @@ Version and helper macros
215
215
 
216
216
  #include <fcntl.h>
217
217
  #include <sys/stat.h>
218
+ #ifndef __MINGW32__
218
219
  #include <sys/time.h>
220
+ #endif
219
221
  #include <unistd.h>
222
+ #ifdef __MINGW32__
223
+ #include <winsock2.h>
224
+ #include <winsock.h>
225
+ #include <ws2tcpip.h>
226
+ #endif
220
227
 
221
228
  #if !defined(__GNUC__) && !defined(__clang__) && !defined(FIO_GNUC_BYPASS)
222
229
  #define __attribute__(...)
@@ -243,6 +250,25 @@ Version and helper macros
243
250
  #include <sys/socket.h>
244
251
  #endif
245
252
 
253
+ #ifdef __MINGW32__
254
+ #define __S_IFMT 0170000
255
+ #define __S_IFLNK 0120000
256
+ #define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask))
257
+ #define S_ISLNK(mode) __S_ISTYPE((mode), __S_IFLNK)
258
+
259
+ #define SIGKILL 9
260
+ #define SIGTERM 15
261
+ #define SIGCONT 17
262
+
263
+ #define pipe(fds) _pipe(fds, 65536, _O_BINARY)
264
+
265
+ int fork(void);
266
+ int kill(int, int);
267
+ ssize_t pread(int, void*, size_t, off_t);
268
+ ssize_t pwrite(int, const void *, size_t, off_t);
269
+ int fio_osffd4fd(unsigned int);
270
+ #endif
271
+
246
272
  /* *****************************************************************************
247
273
  Patch for OSX version < 10.12 from https://stackoverflow.com/a/9781275/4025095
248
274
  ***************************************************************************** */
@@ -2068,7 +2094,7 @@ FIO_FUNC inline int fio_trylock(fio_lock_i *lock);
2068
2094
  /**
2069
2095
  * Releases a spinlock. Releasing an unacquired lock will break it.
2070
2096
  *
2071
- * Returns a non-zero value on success, or 0 if the lock was in an unloacked
2097
+ * Returns a non-zero value on success, or 0 if the lock was in an unlocked
2072
2098
  * state.
2073
2099
  */
2074
2100
  FIO_FUNC inline int fio_unlock(fio_lock_i *lock);
@@ -2539,8 +2565,9 @@ FIO_FUNC inline uint64_t fio_risky_hash(const void *data_, size_t len,
2539
2565
  uint64_t result = fio_lrot64(v0, 17) + fio_lrot64(v1, 13) +
2540
2566
  fio_lrot64(v2, 47) + fio_lrot64(v3, 57);
2541
2567
 
2542
- len ^= (len << 33);
2543
- result += len;
2568
+ uint64_t len64 = len;
2569
+ len64 ^= (len64 << 33);
2570
+ result += len64;
2544
2571
 
2545
2572
  result += v0 * RISKY_PRIME_1;
2546
2573
  result ^= fio_lrot64(result, 13);
@@ -2931,9 +2958,9 @@ C++ extern end
2931
2958
  /**
2932
2959
  * The logarithmic value for a memory block, 15 == 32Kb, 16 == 64Kb, etc'
2933
2960
  *
2934
- * By default, a block of memory is 32Kb silce from an 8Mb allocation.
2961
+ * By default, a block of memory is a 32Kb slice from an 8Mb allocation.
2935
2962
  *
2936
- * A value of 16 will make this a 64Kb silce from a 16Mb allocation.
2963
+ * A value of 16 will make this a 64Kb slice from a 16Mb allocation.
2937
2964
  */
2938
2965
  #define FIO_MEMORY_BLOCK_SIZE_LOG (15)
2939
2966
  #endif
@@ -3000,7 +3027,7 @@ FIO_FUNC inline int fio_trylock(fio_lock_i *lock) {
3000
3027
  /**
3001
3028
  * Releases a spinlock. Releasing an unacquired lock will break it.
3002
3029
  *
3003
- * Returns a non-zero value on success, or 0 if the lock was in an unloacked
3030
+ * Returns a non-zero value on success, or 0 if the lock was in an unlocked
3004
3031
  * state.
3005
3032
  */
3006
3033
  FIO_FUNC inline int fio_unlock(fio_lock_i *lock) {
@@ -3864,6 +3891,7 @@ FIO_FUNC char *fio_str_detach(fio_str_s *s) {
3864
3891
  }
3865
3892
  /* make a copy */
3866
3893
  void *tmp = FIO_MALLOC(i.len + 1);
3894
+ FIO_ASSERT_ALLOC(tmp);
3867
3895
  memcpy(tmp, i.data, i.len + 1);
3868
3896
  i.data = tmp;
3869
3897
  } else {
@@ -3874,6 +3902,7 @@ FIO_FUNC char *fio_str_detach(fio_str_s *s) {
3874
3902
  } else if (s->dealloc != FIO_FREE) {
3875
3903
  /* make a copy */
3876
3904
  void *tmp = FIO_MALLOC(i.len + 1);
3905
+ FIO_ASSERT_ALLOC(tmp);
3877
3906
  memcpy(tmp, i.data, i.len + 1);
3878
3907
  i.data = tmp;
3879
3908
  if (s->dealloc)
@@ -4338,7 +4367,7 @@ inline FIO_FUNC fio_str_info_s fio_str_write_i(fio_str_s *s, int64_t num) {
4338
4367
  fio_str_info_s i;
4339
4368
  if (!num)
4340
4369
  goto zero;
4341
- char buf[22];
4370
+ char buf[22] = {0};
4342
4371
  uint64_t l = 0;
4343
4372
  uint8_t neg;
4344
4373
  if ((neg = (num < 0))) {
@@ -4472,7 +4501,7 @@ FIO_FUNC fio_str_info_s fio_str_readfile(fio_str_s *s, const char *filename,
4472
4501
  intptr_t start_at, intptr_t limit) {
4473
4502
  fio_str_info_s state = {.data = NULL};
4474
4503
  #if defined(__unix__) || defined(__linux__) || defined(__APPLE__) || \
4475
- defined(__CYGWIN__)
4504
+ defined(__CYGWIN__) || defined(__MINGW32__)
4476
4505
  /* POSIX implementations. */
4477
4506
  if (filename == NULL || !s)
4478
4507
  return state;
@@ -4502,7 +4531,7 @@ FIO_FUNC fio_str_info_s fio_str_readfile(fio_str_s *s, const char *filename,
4502
4531
  }
4503
4532
  }
4504
4533
 
4505
- if (stat(filename, &f_data)) {
4534
+ if (stat(filename, &f_data) == -1) {
4506
4535
  goto finish;
4507
4536
  }
4508
4537
 
@@ -4510,9 +4539,12 @@ FIO_FUNC fio_str_info_s fio_str_readfile(fio_str_s *s, const char *filename,
4510
4539
  state = fio_str_info(s);
4511
4540
  goto finish;
4512
4541
  }
4513
-
4542
+ #ifdef __MINGW32__
4543
+ file = _open(filename, O_RDONLY);
4544
+ #else
4514
4545
  file = open(filename, O_RDONLY);
4515
- if (-1 == file)
4546
+ #endif
4547
+ if (file == -1)
4516
4548
  goto finish;
4517
4549
 
4518
4550
  if (start_at < 0) {
@@ -4531,7 +4563,11 @@ FIO_FUNC fio_str_info_s fio_str_readfile(fio_str_s *s, const char *filename,
4531
4563
  state.data = NULL;
4532
4564
  state.len = state.capa = 0;
4533
4565
  }
4566
+ #ifdef __MINGW32__
4567
+ _close(file);
4568
+ #else
4534
4569
  close(file);
4570
+ #endif
4535
4571
  finish:
4536
4572
  FIO_FREE(path);
4537
4573
  return state;
@@ -6012,7 +6048,7 @@ FIO_NAME(_insert_or_overwrite_)(FIO_NAME(s) * set, FIO_SET_HASH_TYPE hash_value,
6012
6048
  pos->hash = hash_value;
6013
6049
  pos->pos->hash = hash_value;
6014
6050
  FIO_SET_COPY(pos->pos->obj, obj);
6015
-
6051
+
6016
6052
  return pos->pos->obj;
6017
6053
  }
6018
6054
 
@@ -6282,7 +6318,7 @@ restart:
6282
6318
  FIO_LOG_FATAL(
6283
6319
  "facil.io Set / Hash Map has too many collisions (%zu/%zu)."
6284
6320
  "\n\t\tthis is a fatal implementation error,"
6285
- "please report this issue at facio.io's open source project"
6321
+ "please report this issue at facil.io's open source project"
6286
6322
  "\n\t\tNote: hash maps and sets should never reach this point."
6287
6323
  "\n\t\tThey should be guarded against collision attacks.",
6288
6324
  set->pos, set->capa);
data/ext/iodine/fio_cli.c CHANGED
@@ -50,7 +50,7 @@ typedef struct {
50
50
  #define AVOID_MACRO
51
51
 
52
52
  #define FIO_CLI_HASH_VAL(s) \
53
- fio_risky_hash((s).data, (s).len, (uint64_t)fio_cli_start)
53
+ fio_risky_hash((s).data, (s).len, (uintptr_t)fio_cli_start)
54
54
 
55
55
  /* *****************************************************************************
56
56
  CLI Parsing
@@ -4,6 +4,13 @@ License: MIT
4
4
 
5
5
  Feel free to copy, use and enjoy according to the license provided.
6
6
  */
7
+ #ifdef __MINGW32__
8
+ // make pedantic compiler happy
9
+ typedef struct {
10
+ int bogus;
11
+ } bogus_s;
12
+
13
+ #else
7
14
  #include <fio.h>
8
15
 
9
16
  /**
@@ -639,3 +646,4 @@ void FIO_TLS_WEAK fio_tls_destroy(fio_tls_s *tls) {
639
646
  }
640
647
 
641
648
  #endif /* Library compiler flags */
649
+ #endif
@@ -4,6 +4,13 @@ License: MIT
4
4
 
5
5
  Feel free to copy, use and enjoy according to the license provided.
6
6
  */
7
+ #ifdef __MINGW32__
8
+ // make pedantic compiler happy
9
+ typedef struct {
10
+ int bogus;
11
+ } bogus_s;
12
+
13
+ #else
7
14
  #include <fio.h>
8
15
 
9
16
  /**
@@ -1046,3 +1053,4 @@ void FIO_TLS_WEAK fio_tls_destroy(fio_tls_s *tls) {
1046
1053
  }
1047
1054
 
1048
1055
  #endif /* Library compiler flags */
1056
+ #endif
@@ -18,10 +18,22 @@ License: MIT
18
18
  #include <sys/types.h>
19
19
  #include <unistd.h>
20
20
 
21
+ #ifdef __MINGW32__
22
+ #include <fileapi.h>
23
+ #endif
24
+
21
25
  static inline int fio_tmpfile(void) {
22
26
  // create a temporary file to contain the data.
23
27
  int fd = 0;
24
- #ifdef P_tmpdir
28
+ #ifdef __MINGW32__
29
+ char name_template[] = "fio";
30
+ TCHAR temp_path[(MAX_PATH-14)];
31
+ TCHAR temp_filename[MAX_PATH];
32
+ GetTempPath(MAX_PATH - 14, temp_path);
33
+ GetTempFileNameA(temp_path, name_template, 0, temp_filename);
34
+ fd = _open(temp_filename, _O_CREAT | _O_RDWR);
35
+ _chmod(temp_filename, _S_IREAD | _S_IWRITE);
36
+ #elif defined(P_tmpdir)
25
37
  if (P_tmpdir[sizeof(P_tmpdir) - 1] == '/') {
26
38
  char name_template[] = P_tmpdir "facil_io_tmpfile_XXXXXXXX";
27
39
  fd = mkstemp(name_template);
@@ -1,5 +1,5 @@
1
1
  #if defined(__unix__) || defined(__APPLE__) || defined(__linux__) || \
2
- defined(__CYGWIN__) /* require POSIX */
2
+ defined(__CYGWIN__) || defined(__MINGW32__) /* require POSIX */
3
3
  /*
4
4
  Copyright: Boaz Segev, 2017-2019
5
5
  License: MIT
@@ -78,6 +78,7 @@ static void fiobj_data_copy_parent(FIOBJ o) {
78
78
  switch (obj2io(obj2io(o)->source.parent)->fd) {
79
79
  case -1:
80
80
  obj2io(o)->buffer = fio_malloc(obj2io(o)->len + 1);
81
+ FIO_ASSERT_ALLOC(obj2io(o)->buffer);
81
82
  memcpy(obj2io(o)->buffer,
82
83
  obj2io(obj2io(o)->source.parent)->buffer + obj2io(o)->capa,
83
84
  obj2io(o)->len);
@@ -102,7 +103,11 @@ static void fiobj_data_copy_parent(FIOBJ o) {
102
103
  if (data.len + pos > obj2io(o)->len)
103
104
  data.len = obj2io(o)->len - pos;
104
105
  retry_int:
106
+ #ifdef __MINGW32__
107
+ written = pwrite(obj2io(o)->fd, data.data, data.len, 0);
108
+ #else
105
109
  written = write(obj2io(o)->fd, data.data, data.len);
110
+ #endif
106
111
  if (written < 0) {
107
112
  if (errno == EINTR)
108
113
  goto retry_int;
@@ -958,7 +963,6 @@ intptr_t fiobj_data_write(FIOBJ io, void *buffer, uintptr_t length) {
958
963
  /* Unslice slices */
959
964
  if (obj2io(io)->fd == -2)
960
965
  fiobj_data_assert_dynamic(io);
961
-
962
966
  if (obj2io(io)->fd == -1) {
963
967
  /* String Code */
964
968
  fiobj_data_pre_write(io, length + 1);
@@ -967,7 +971,6 @@ intptr_t fiobj_data_write(FIOBJ io, void *buffer, uintptr_t length) {
967
971
  obj2io(io)->buffer[obj2io(io)->len] = 0;
968
972
  return length;
969
973
  }
970
-
971
974
  /* File Code */
972
975
  return pwrite(obj2io(io)->fd, buffer, length, fiobj_data_get_fd_size(io));
973
976
  }
@@ -1046,7 +1049,6 @@ void fiobj_data_test(void) {
1046
1049
  fprintf(stderr, "* `fiobj_data_read` operation overflow - FAILED!\n");
1047
1050
  exit(-1);
1048
1051
  }
1049
-
1050
1052
  if (fiobj_obj2cstr(strio).len != fiobj_obj2cstr(text).len ||
1051
1053
  fiobj_obj2cstr(fdio).len != fiobj_obj2cstr(text).len) {
1052
1054
  fprintf(stderr, "* `write` operation FAILED!\n");
@@ -3,7 +3,8 @@ Copyright: Boaz Segev, 2017-2019
3
3
  License: MIT
4
4
  */
5
5
  #if !defined(H_FIOBJ_IO_H) && (defined(__unix__) || defined(__APPLE__) || \
6
- defined(__linux__) || defined(__CYGWIN__))
6
+ defined(__linux__) || defined(__CYGWIN__) || \
7
+ defined(__MINGW32__))
7
8
 
8
9
  /**
9
10
  * A dynamic type for reading / writing to a local file, a temporary file or an
@@ -36,6 +36,8 @@ License: MIT
36
36
 
37
37
  #include <errno.h>
38
38
 
39
+ #include <pthread.h>
40
+
39
41
  /* *****************************************************************************
40
42
  Hash types
41
43
  ***************************************************************************** */
@@ -69,18 +71,34 @@ static void fiobj_hash_dealloc(FIOBJ o, void (*task)(FIOBJ, void *),
69
71
  fio_free(FIOBJ2PTR(o));
70
72
  }
71
73
 
72
- static __thread FIOBJ each_at_key = FIOBJ_INVALID;
74
+ static pthread_key_t each_at_key;
75
+ static pthread_once_t each_at_key_once = PTHREAD_ONCE_INIT;
76
+ static void init_each_at_key(void) {
77
+ pthread_key_create(&each_at_key, free);
78
+ }
79
+ static void init_each_at_key_ptr(void) {
80
+ FIOBJ *eak = malloc(sizeof(FIOBJ));
81
+ FIO_ASSERT_ALLOC(eak);
82
+ *eak = FIOBJ_INVALID;
83
+ pthread_setspecific(each_at_key, eak);
84
+ }
73
85
 
74
86
  static size_t fiobj_hash_each1(FIOBJ o, size_t start_at,
75
87
  int (*task)(FIOBJ obj, void *arg), void *arg) {
76
88
  assert(o && FIOBJ_TYPE_IS(o, FIOBJ_T_HASH));
77
- FIOBJ old_each_at_key = each_at_key;
89
+ pthread_once(&each_at_key_once, init_each_at_key);
90
+ FIOBJ *each_at_key_ptr = (FIOBJ *)pthread_getspecific(each_at_key);
91
+ if (!each_at_key_ptr) {
92
+ init_each_at_key_ptr();
93
+ each_at_key_ptr = (FIOBJ *)pthread_getspecific(each_at_key);
94
+ }
95
+ FIOBJ old_each_at_key = *each_at_key_ptr;
78
96
  fio_hash___s *hash = &obj2hash(o)->hash;
79
97
  size_t count = 0;
80
98
  if (hash->count == hash->pos) {
81
99
  /* no holes in the hash, we can work as we please. */
82
100
  for (count = start_at; count < hash->count; ++count) {
83
- each_at_key = hash->ordered[count].obj.key;
101
+ *each_at_key_ptr = hash->ordered[count].obj.key;
84
102
  if (task((FIOBJ)hash->ordered[count].obj.obj, arg) == -1) {
85
103
  ++count;
86
104
  goto end;
@@ -100,17 +118,25 @@ static size_t fiobj_hash_each1(FIOBJ o, size_t start_at,
100
118
  if (hash->ordered[pos].obj.key == FIOBJ_INVALID)
101
119
  continue;
102
120
  ++count;
103
- each_at_key = hash->ordered[pos].obj.key;
121
+ *each_at_key_ptr = hash->ordered[pos].obj.key;
104
122
  if (task((FIOBJ)hash->ordered[pos].obj.obj, arg) == -1)
105
123
  break;
106
124
  }
107
125
  }
108
126
  end:
109
- each_at_key = old_each_at_key;
127
+ *each_at_key_ptr = old_each_at_key;
110
128
  return count;
111
129
  }
112
130
 
113
- FIOBJ fiobj_hash_key_in_loop(void) { return each_at_key; }
131
+ FIOBJ fiobj_hash_key_in_loop(void) {
132
+ pthread_once(&each_at_key_once, init_each_at_key);
133
+ FIOBJ *each_at_key_ptr = (FIOBJ *)pthread_getspecific(each_at_key);
134
+ if (!each_at_key_ptr) {
135
+ init_each_at_key_ptr();
136
+ each_at_key_ptr = (FIOBJ *)pthread_getspecific(each_at_key);
137
+ }
138
+ return *each_at_key_ptr;
139
+ }
114
140
 
115
141
  static size_t fiobj_hash_is_eq(const FIOBJ self, const FIOBJ other) {
116
142
  if (fio_hash___count(&obj2hash(self)->hash) !=
@@ -240,12 +240,20 @@ Testing
240
240
  #if DEBUG
241
241
  static inline void mustache_save2file(char const *filename, char const *data,
242
242
  size_t length) {
243
+ #ifdef __MINGW32__
244
+ int fd = _open(filename, _O_CREAT | _O_RDWR);
245
+ #else
243
246
  int fd = open(filename, O_CREAT | O_RDWR, 0);
247
+ #endif
244
248
  if (fd == -1) {
245
249
  perror("Couldn't open / create file for template testing");
246
250
  exit(-1);
247
251
  }
252
+ #ifdef __MINGW32__
253
+ _chmod(filename, _S_IREAD | _S_IWRITE);
254
+ #else
248
255
  fchmod(fd, 0777);
256
+ #endif
249
257
  if (pwrite(fd, data, length, 0) != (ssize_t)length) {
250
258
  perror("Mustache template write error");
251
259
  exit(-1);
@@ -265,6 +273,7 @@ void fiobj_mustache_test(void) {
265
273
  "{{=<< >>=}}* Users:\r\n<<#users>><<id>>. <<& name>> "
266
274
  "(<<name>>)\r\n<</users>>\r\nNested: <<& nested.item >>.";
267
275
  char const *template_name = "mustache_test_template.mustache";
276
+ fprintf(stderr, "mustache test saving template %s\n", template_name);
268
277
  mustache_save2file(template_name, template, strlen(template));
269
278
  mustache_s *m =
270
279
  fiobj_mustache_load((fio_str_info_s){.data = (char *)template_name});
@@ -12,6 +12,8 @@ License: MIT
12
12
  #include <errno.h>
13
13
  #include <math.h>
14
14
 
15
+ #include <pthread.h>
16
+
15
17
  /* *****************************************************************************
16
18
  Numbers Type
17
19
  ***************************************************************************** */
@@ -33,7 +35,17 @@ typedef struct {
33
35
  Numbers VTable
34
36
  ***************************************************************************** */
35
37
 
36
- static __thread char num_buffer[512];
38
+ static pthread_key_t num_vt_buffer_key;
39
+ static pthread_once_t num_vt_buffer_once = PTHREAD_ONCE_INIT;
40
+ static void init_num_vt_buffer_key(void) {
41
+ pthread_key_create(&num_vt_buffer_key, free);
42
+ }
43
+ static void init_num_vt_buffer_ptr(void) {
44
+ char *num_vt_buffer = malloc(sizeof(char)*512);
45
+ FIO_ASSERT_ALLOC(num_vt_buffer);
46
+ memset(num_vt_buffer, 0, sizeof(char)*512);
47
+ pthread_setspecific(num_vt_buffer_key, num_vt_buffer);
48
+ }
37
49
 
38
50
  static intptr_t fio_i2i(const FIOBJ o) { return obj2num(o)->i; }
39
51
  static intptr_t fio_f2i(const FIOBJ o) {
@@ -46,6 +58,12 @@ static size_t fio_itrue(const FIOBJ o) { return (obj2num(o)->i != 0); }
46
58
  static size_t fio_ftrue(const FIOBJ o) { return (obj2float(o)->f != 0); }
47
59
 
48
60
  static fio_str_info_s fio_i2str(const FIOBJ o) {
61
+ pthread_once(&num_vt_buffer_once, init_num_vt_buffer_key);
62
+ char *num_buffer = pthread_getspecific(num_vt_buffer_key);
63
+ if (!num_buffer) {
64
+ init_num_vt_buffer_ptr();
65
+ num_buffer = pthread_getspecific(num_vt_buffer_key);
66
+ }
49
67
  return (fio_str_info_s){
50
68
  .data = num_buffer,
51
69
  .len = fio_ltoa(num_buffer, obj2num(o)->i, 10),
@@ -60,6 +78,12 @@ static fio_str_info_s fio_f2str(const FIOBJ o) {
60
78
  else
61
79
  return (fio_str_info_s){.data = (char *)"-Infinity", .len = 9};
62
80
  }
81
+ pthread_once(&num_vt_buffer_once, init_num_vt_buffer_key);
82
+ char *num_buffer = pthread_getspecific(num_vt_buffer_key);
83
+ if (!num_buffer) {
84
+ init_num_vt_buffer_ptr();
85
+ num_buffer = pthread_getspecific(num_vt_buffer_key);
86
+ }
63
87
  return (fio_str_info_s){
64
88
  .data = num_buffer,
65
89
  .len = fio_ftoa(num_buffer, obj2float(o)->f, 10),
@@ -126,14 +150,30 @@ FIOBJ fiobj_num_new_bignum(intptr_t num) {
126
150
  // FIOBJ_IS_ALLOCATED(target)); obj2num(target)->i = num;
127
151
  // }
128
152
 
153
+ static pthread_key_t num_ret_key;
154
+ static pthread_once_t num_ret_once = PTHREAD_ONCE_INIT;
155
+ static void init_num_ret_key(void) {
156
+ pthread_key_create(&num_ret_key, free);
157
+ }
158
+ static void init_num_ret_ptr(void) {
159
+ fiobj_num_s *ret = malloc(sizeof(fiobj_num_s));
160
+ FIO_ASSERT_ALLOC(ret);
161
+ memset(ret, 0, sizeof(fiobj_num_s));
162
+ pthread_setspecific(num_ret_key, ret);
163
+ }
129
164
  /** Creates a temporary Number object. This ignores `fiobj_free`. */
130
165
  FIOBJ fiobj_num_tmp(intptr_t num) {
131
- static __thread fiobj_num_s ret;
132
- ret = (fiobj_num_s){
166
+ pthread_once(&num_ret_once, init_num_ret_key);
167
+ fiobj_num_s *ret = pthread_getspecific(num_ret_key);
168
+ if (!ret) {
169
+ init_num_ret_ptr();
170
+ ret = pthread_getspecific(num_ret_key);
171
+ }
172
+ *ret = (fiobj_num_s){
133
173
  .head = {.type = FIOBJ_T_NUMBER, .ref = ((~(uint32_t)0) >> 4)},
134
174
  .i = num,
135
175
  };
136
- return (FIOBJ)&ret;
176
+ return (FIOBJ)ret;
137
177
  }
138
178
 
139
179
  /* *****************************************************************************
@@ -164,10 +204,26 @@ void fiobj_float_set(FIOBJ obj, double num) {
164
204
  obj2float(obj)->f = num;
165
205
  }
166
206
 
207
+ static pthread_key_t float_ret_key;
208
+ static pthread_once_t float_ret_once = PTHREAD_ONCE_INIT;
209
+ static void init_float_ret_key(void) {
210
+ pthread_key_create(&float_ret_key, free);
211
+ }
212
+ static void init_float_ret_ptr(void) {
213
+ fiobj_float_s *ret = malloc(sizeof(fiobj_float_s));
214
+ FIO_ASSERT_ALLOC(ret);
215
+ memset(ret, 0, sizeof(fiobj_float_s));
216
+ pthread_setspecific(float_ret_key, ret);
217
+ }
167
218
  /** Creates a temporary Number object. This ignores `fiobj_free`. */
168
219
  FIOBJ fiobj_float_tmp(double num) {
169
- static __thread fiobj_float_s ret;
170
- ret = (fiobj_float_s){
220
+ pthread_once(&float_ret_once, init_float_ret_key);
221
+ fiobj_float_s *ret = pthread_getspecific(float_ret_key);
222
+ if (!ret) {
223
+ init_float_ret_ptr();
224
+ ret = pthread_getspecific(float_ret_key);
225
+ }
226
+ *ret = (fiobj_float_s){
171
227
  .head =
172
228
  {
173
229
  .type = FIOBJ_T_FLOAT,
@@ -175,20 +231,42 @@ FIOBJ fiobj_float_tmp(double num) {
175
231
  },
176
232
  .f = num,
177
233
  };
178
- return (FIOBJ)&ret;
234
+ return (FIOBJ)ret;
179
235
  }
180
236
 
181
237
  /* *****************************************************************************
182
238
  Numbers to Strings - Buffered
183
239
  ***************************************************************************** */
184
240
 
185
- static __thread char num_buffer[512];
241
+ static pthread_key_t num_str_buffer_key;
242
+ static pthread_once_t num_str_buffer_once = PTHREAD_ONCE_INIT;
243
+ static void init_num_str_buffer_key(void) {
244
+ pthread_key_create(&num_str_buffer_key, free);
245
+ }
246
+ static void init_num_str_buffer_ptr(void) {
247
+ char *num_str_buffer = malloc(sizeof(char)*512);
248
+ FIO_ASSERT_ALLOC(num_str_buffer);
249
+ memset(num_str_buffer, 0, sizeof(char)*512);
250
+ pthread_setspecific(num_str_buffer_key, num_str_buffer);
251
+ }
186
252
 
187
253
  fio_str_info_s fio_ltocstr(long i) {
254
+ pthread_once(&num_str_buffer_once, init_num_str_buffer_key);
255
+ char *num_buffer = pthread_getspecific(num_str_buffer_key);
256
+ if (!num_buffer) {
257
+ init_num_str_buffer_ptr();
258
+ num_buffer = pthread_getspecific(num_str_buffer_key);
259
+ }
188
260
  return (fio_str_info_s){.data = num_buffer,
189
261
  .len = fio_ltoa(num_buffer, i, 10)};
190
262
  }
191
263
  fio_str_info_s fio_ftocstr(double f) {
264
+ pthread_once(&num_str_buffer_once, init_num_str_buffer_key);
265
+ char *num_buffer = pthread_getspecific(num_str_buffer_key);
266
+ if (!num_buffer) {
267
+ init_num_str_buffer_ptr();
268
+ num_buffer = pthread_getspecific(num_str_buffer_key);
269
+ }
192
270
  return (fio_str_info_s){.data = num_buffer,
193
271
  .len = fio_ftoa(num_buffer, f, 10)};
194
272
  }
@@ -37,6 +37,8 @@ License: MIT
37
37
  #define PATH_MAX PAGE_SIZE
38
38
  #endif
39
39
 
40
+ #include <pthread.h>
41
+
40
42
  /* *****************************************************************************
41
43
  String Type
42
44
  ***************************************************************************** */
@@ -176,22 +178,33 @@ FIOBJ fiobj_str_move(char *str, size_t len, size_t capacity) {
176
178
  return ((uintptr_t)s | FIOBJECT_STRING_FLAG);
177
179
  }
178
180
 
181
+ static pthread_key_t str_tmp_key;
182
+ static pthread_once_t str_tmp_once = PTHREAD_ONCE_INIT;
183
+ static void init_str_tmp_key(void) {
184
+ pthread_key_create(&str_tmp_key, free);
185
+ }
186
+ static void init_str_tmp_key_ptr(void) {
187
+ fiobj_str_s *tmp = malloc(sizeof(fiobj_str_s));
188
+ FIO_ASSERT_ALLOC(tmp);
189
+ tmp->head.ref = ((~(uint32_t)0) >> 4);
190
+ tmp->head.type = FIOBJ_T_STRING;
191
+ tmp->str.small = 1;
192
+ pthread_setspecific(str_tmp_key, tmp);
193
+ }
179
194
  /**
180
195
  * Returns a thread-static temporary string. Avoid calling `fiobj_dup` or
181
196
  * `fiobj_free`.
182
197
  */
183
198
  FIOBJ fiobj_str_tmp(void) {
184
- static __thread fiobj_str_s tmp = {
185
- .head =
186
- {
187
- .ref = ((~(uint32_t)0) >> 4),
188
- .type = FIOBJ_T_STRING,
189
- },
190
- .str = {.small = 1},
191
- };
192
- tmp.str.frozen = 0;
193
- fio_str_resize(&tmp.str, 0);
194
- return ((uintptr_t)&tmp | FIOBJECT_STRING_FLAG);
199
+ pthread_once(&str_tmp_once, init_str_tmp_key);
200
+ fiobj_str_s *tmp = (fiobj_str_s *)pthread_getspecific(str_tmp_key);
201
+ if (!tmp) {
202
+ init_str_tmp_key_ptr();
203
+ tmp = (fiobj_str_s *)pthread_getspecific(str_tmp_key);
204
+ }
205
+ tmp->str.frozen = 0;
206
+ fio_str_resize(&tmp->str, 0);
207
+ return ((uintptr_t)tmp | FIOBJECT_STRING_FLAG);
195
208
  }
196
209
 
197
210
  /** Prevents the String object from being changed. */
@@ -102,7 +102,7 @@ size_t __attribute__((weak)) fio_ltoa(char *dest, int64_t num, uint8_t base) {
102
102
  '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
103
103
 
104
104
  size_t len = 0;
105
- char buf[48]; /* we only need up to 20 for base 10, but base 3 needs 41... */
105
+ char buf[48] = {0}; /* we only need up to 20 for base 10, but base 3 needs 41... */
106
106
 
107
107
  if (!num)
108
108
  goto zero;
@@ -502,7 +502,7 @@ fio_str_info_s fio_ftocstr(double);
502
502
  /**
503
503
  * Returns a C String (NUL terminated) using the `fio_str_info_s` data type.
504
504
  *
505
- * The Sting in binary safe and might contain NUL bytes in the middle as well as
505
+ * The String is binary safe and might contain NUL bytes in the middle as well as
506
506
  * a terminating NUL.
507
507
  *
508
508
  * If a a Number or a Float are passed to the function, they
@@ -554,11 +554,13 @@ FIO_INLINE uint64_t fiobj_obj2hash(const FIOBJ o) {
554
554
  if (!FIOBJ_IS_ALLOCATED(o))
555
555
  return (uint64_t)o;
556
556
  fio_str_info_s s = fiobj_obj2cstr(o);
557
- return FIO_HASH_FN(s.data, s.len, &fiobj_each2, &fiobj_free_complex_object);
557
+ return FIO_HASH_FN(s.data, s.len, (uintptr_t)&fiobj_each2,
558
+ (uintptr_t)&fiobj_free_complex_object);
558
559
  }
559
560
 
560
561
  FIO_INLINE uint64_t fiobj_hash_string(const void *data, size_t len) {
561
- return FIO_HASH_FN(data, len, &fiobj_each2, &fiobj_free_complex_object);
562
+ return FIO_HASH_FN(data, len, (uintptr_t)&fiobj_each2,
563
+ (uintptr_t)&fiobj_free_complex_object);
562
564
  }
563
565
 
564
566
  /**