Follow-up to a patch for GCSORT in [834a81d7be] which uses threads for sorting - and for doing that used libcob's cob_get_llint()function - here's the complete rabbit hole - things to work on:
cob_get_llint() does an internal call of cob_move() from any floating point field to a long long int. This goes then to
case COB_TYPE_NUMERIC_DOUBLE:
case COB_TYPE_NUMERIC_FLOAT:
case COB_TYPE_NUMERIC_L_DOUBLE:
case COB_TYPE_NUMERIC_FP_BIN32:
case COB_TYPE_NUMERIC_FP_BIN64:
case COB_TYPE_NUMERIC_FP_BIN128:
case COB_TYPE_NUMERIC_FP_DEC64:
case COB_TYPE_NUMERIC_FP_DEC128:
cob_decimal_setget_fld (src, dst, 0);
... and this... uses the static cob_decimal cob_d1:
cob_decimal_set_field (&cob_d1, src);
(void)cob_decimal_get_field (&cob_d1, dst, opt | COB_STORE_NO_SIZE_ERROR);
... checking the code (all in numeric.c) for similar cases: the internal decimals as well as (since gc 2.2) the "allocate decimals" that programs request for computation and expressions are static pre-allocated.
This necessary to achieve a small memory footprint and good performance; it also works fine with different programs keeping the same address to them in program-local pointers, as they are only used within an expression and there is only one handled at the same time - even if hundreds of programs point to the same ones...
Also note that those are only used for "complex" cases, many easy ones are optimized away in codegen, constants may be handled different as well.
But as soon as you have those "complex" numeric expressions or computations executed at exactly the same time, then those can clash - as is the case in cob_get_llint().
This ticket is about fixing that, but foremost we need a good plan to do so, as allocating those in all programs is not possible (a huge performance penalty).
We may be able to put those in thread-local storage - but then we need to have a thread-local part of cob_init_numeric and cob_exit_numeric as well.
The easy option is to let the caller handle this with a call to cob_cleanup_thread()and cob_init_thread() - which we seem to (partially) have for strings.c.
The complex one is doing it automatically (at least "if possible" - then just calling those functions internally).