Skip to content

Commit

Permalink
[#205] Ensure TP worker thread does not invoke YottaDB engine (even t…
Browse files Browse the repository at this point in the history
…o issue an error); Nix NOTSUPSTAPI message

The simplethreadapi/tp subtest failed once with the following signature in the
tp5_TPTIMEOUT.c section of the test.

%YDB-F-ASSERT, Assert failed in sr_unix/gt_timers.c line 725 for expression
	(gtm_is_main_thread() || gtm_jvm_process || exit_handler_active && (DUMMY_SIG_NUM == why))

with the following C-stack

(gdb) where
 #0  __pthread_kill (threadid=<optimized out>, signo=3) at ../sysdeps/unix/sysv/linux/pthread_kill.c:62
 #1  gtm_dump_core () at sr_unix/gtm_dump_core.c:72
 #2  gtm_fork_n_core () at sr_unix/gtm_fork_n_core.c:148
 #3  ch_cond_core () at sr_unix/ch_cond_core.c:64
 #4  rts_error_va (csa=0x0, argcnt=7, var=0x7fe3a13888b0) at sr_unix/rts_error.c:194
 #5  rts_error_csa (csa=0x0, argcnt=7) at sr_unix/rts_error.c:101
 #6  timer_handler (why=0) at sr_unix/gt_timers.c:725
 #7  check_for_deferred_timers () at sr_unix/gt_timers.c:1179
 #8  deferred_signal_handler () at sr_port/deferred_signal_handler.c:49
 #9  rts_error_va (csa=0x0, argcnt=4, var=0x7fe3a1388c70) at sr_unix/rts_error.c:194
 #10 rts_error_csa (csa=0x0, argcnt=4) at sr_unix/rts_error.c:101
 #11 ydb_hiber_start (sleep_nsec=1000000) at sr_unix/ydb_hiber_start.c:46
 #12 gvnset (tptoken=1) at tp5_TPTIMEOUT.c:77
 #13 ydb_stm_tpthreadq_process (curTPWorkQHead=0x13dac40) at sr_unix/ydb_stm_tpthread.c:197
 #14 ydb_stm_tpthread (parm=0x0) at sr_unix/ydb_stm_tpthread.c:78
 #15 start_thread (arg=0x7fe3a1389700) at pthread_create.c:333
 #16 clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109

This was a process that had already made SimpleThreadAPI calls but is now making a SimpleAPI call
(ydb_hiber_start()) and so a NOTSUPSTAPI error is about to be issued. But since this call is happening
in the user-defined callback function inside a TP transaction, it is the TP worker thread (not the
MAIN worker thread) that is executing the "ydb_hiber_start". This means the rts_error_csa invocation
is running in the TP worker thread while the YottaDB engine is concurrently being modified by the
MAIN worker thread. A no-no since the YottaDB engine is not multi-threaded.

To fix this issue, the VERIFY_NON_THREADED_API macro is now fixed to do a "return YDB_ERR_INVAPIMODE".
This means ydb_hiber_start() would return a lot sooner thereby not requiring an "rts_error" invocation.

But while doing this change, noticed a few issues. The VERIFY_NON_THREADED_API is used from a few
functions that do not return any value (sr_unix/ydb_free.c and sr_unix/ydb_timer_cancel.c) so a new
macro VERIFY_NON_THREADED_API_NORETVAL is created which is very similar except it does a plain "return".
sr_unix/ydb_malloc.c needed special handling since it was returning a "void *" and so a new
VERIFY_NON_THREADED_API_RETNULL macro is created for that purpose.

While at this, noticed that the VERIFY_NON_THREADED_API macro was not resetting
TREF(libyottadb_active_rtn) in case of an INVAPIMODE return (since this macro is usually invoked
after a LIBYOTTADB_INIT) so fixed it to do so.

Note that the VERIFY_THREADED_API macro stayed the same in that it did not do this reset since it is
usually invoked before the LIBYOTTADB_INIT macro. But two exceptions to this rule were found,
sr_unix/ydb_cip_helper.c and sr_unix/ydb_tp_s_common.c. They are now fixed so the VERIFY_THREADED_API
macro invocation happens before the LIBYOTTADB_INIT macro.

Another issue that was noticed is that "ydb_ci" and "ydb_cip" were not doing a VERIFY_NON_THREADED_API
check like other SimpleAPI calls do so a new sr_unix/ydb_ci.c and sr_unix/ydb_cip.c were created to
do this before invoking ydb_ci_exec(). And the existing ydb_ci() and ydb_cip() function definitions
in sr_unix/gtmci.c were removed. A new VERIFY_NON_THREADED_API_DO_NOT_SHUTOFF_ACTIVE_RTN macro was
introduced for this purpose since we do not want to do a LIBYOTTADB_INIT in these functions (to avoid
unnecessary SIMPLEAPINEST errors).

With all these changes, the NOTSUPSTAPI error (currently issued in sr_unix/ydb_hiber_start_wait_any.c
and sr_unix/ydb_hiber_start.c) was no longer necessary since an INVAPIMODE error would have been issued
before this error codepath  is reached in all callers. So this error message is now removed.
  • Loading branch information
nars1 committed Dec 20, 2018
1 parent 5ffcfba commit 4c4ca46
Show file tree
Hide file tree
Showing 15 changed files with 190 additions and 42 deletions.
3 changes: 1 addition & 2 deletions sr_port/libydberrors2.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,4 @@
#define YDB_ERR_INVLNPAIRLIST -151027930
#define YDB_ERR_INVTPTRANS -151027938
#define YDB_ERR_INVAPIMODE -151027946
#define YDB_ERR_NOTSUPSTAPI -151027954
#define YDB_ERR_STAPIFORKEXEC -151027962
#define YDB_ERR_STAPIFORKEXEC -151027954
3 changes: 1 addition & 2 deletions sr_port/ydberrors.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,4 @@
#define ERR_INVLNPAIRLIST 151027930
#define ERR_INVTPTRANS 151027938
#define ERR_INVAPIMODE 151027946
#define ERR_NOTSUPSTAPI 151027954
#define ERR_STAPIFORKEXEC 151027962
#define ERR_STAPIFORKEXEC 151027954
1 change: 0 additions & 1 deletion sr_port/ydberrors.msg
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ NODEEND <End of list of nodes/subscripts>/error/fao=0
INVLNPAIRLIST <Invalid lockname/subscript pair list (uneven number of lockname/subscript parameters)>/error/fao=0
INVTPTRANS <Invalid TP transaction - either invalid TP token or transaction not in progress>/error/fao=0
INVAPIMODE <Process not allowed to first use !AD then switch to using !AD>/error/fao=4
NOTSUPSTAPI <Calls to !AD are not supported if threaded Simple API functions are in use>/error/fao=2
STAPIFORKEXEC <Calls to YottaDB are not supported after a fork() if threaded Simple API functions were in use in parent. Call exec() first>/error/fao=0
!
! If there are UNUSEDMSG* lines unused for more than one year and at least two non-patch releases, use them before adding new lines.
Expand Down
3 changes: 1 addition & 2 deletions sr_port/ydberrors_ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ LITDEF err_msg ydberrors[] = {
{ "INVLNPAIRLIST", "Invalid lockname/subscript pair list (uneven number of lockname/subscript parameters)", 0 },
{ "INVTPTRANS", "Invalid TP transaction - either invalid TP token or transaction not in progress", 0 },
{ "INVAPIMODE", "Process not allowed to first use !AD then switch to using !AD", 4 },
{ "NOTSUPSTAPI", "Calls to !AD are not supported if threaded Simple API functions are in use", 2 },
{ "STAPIFORKEXEC", "Calls to YottaDB are not supported after a fork() if threaded Simple API functions were in use in parent. Call exec() first", 0 },
};

Expand All @@ -60,7 +59,7 @@ GBLDEF err_ctl ydberrors_ctl = {
256,
"YDB",
&ydberrors[0],
31,
30,
&ydberrors_undocarr[0],
0
};
Expand Down
22 changes: 0 additions & 22 deletions sr_unix/gtmci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1095,28 +1095,6 @@ int ydb_ci_exec(const char *c_rtn_name, void *callin_handle, int populate_handle
return 0;
}

/* Initial call-in driver version - does name lookup on each call */
int ydb_ci(const char *c_rtn_name, ...)
{
va_list var;

VAR_START(var, c_rtn_name);
/* Note: "va_end(var)" done inside "ydb_ci_exec" */
return ydb_ci_exec(c_rtn_name, NULL, FALSE, var, FALSE);
}

/* Fast path call-in driver version - Adds a struct parm that contains name resolution info after first call
* to speed up dispatching.
*/
int ydb_cip(ci_name_descriptor* ci_info, ...)
{
va_list var;

VAR_START(var, ci_info);
/* Note: "va_end(var)" done inside "ydb_ci_exec" */
return ydb_ci_exec(ci_info->rtn_name.address, ci_info->handle, TRUE, var, FALSE);
}

int gtm_ci_filter(const char *c_rtn_name, ...)
{
va_list var;
Expand Down
84 changes: 84 additions & 0 deletions sr_unix/libyottadb_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -654,9 +654,93 @@ MBSTART { \
{ \
if (!IS_STAPI_WORKER_THREAD) \
{ \
SETUP_GENERIC_ERROR_4PARMS(ERR_INVAPIMODE, THREADED_STR_LEN, THREADED_STR, \
UNTHREADED_STR_LEN, UNTHREADED_STR); \
DBGAPITP_ONLY(gtm_fork_n_core()); \
/* Reset active routine indicator before returning an error. \
* Caller would have done LIBYOTTADB_INIT before invoking this macro. Assert that. \
*/ \
assert(LYDB_RTN_NONE != TREF(libyottadb_active_rtn)); \
TREF(libyottadb_active_rtn) = LYDB_RTN_NONE; \
return YDB_ERR_INVAPIMODE; \
} \
/* We are in threaded mode but running an unthreaded command in the main work thread which \
* is allowed. In that case just fall out (verified). \
*/ \
} else \
noThreadAPI_active = TRUE; \
} MBEND

/* Variant of VERIFY_NON_THREADED_API macro that does a "return" but without any value */
#define VERIFY_NON_THREADED_API_NORETVAL \
MBSTART { /* If threaded API but in worker thread, that is OK */ \
GBLREF boolean_t noThreadAPI_active; \
GBLREF boolean_t simpleThreadAPI_active; \
GBLREF stm_workq *stmWorkQueue[]; \
if (simpleThreadAPI_active) \
{ \
if (!IS_STAPI_WORKER_THREAD) \
{ \
SETUP_GENERIC_ERROR_4PARMS(ERR_INVAPIMODE, THREADED_STR_LEN, THREADED_STR, \
UNTHREADED_STR_LEN, UNTHREADED_STR); \
DBGAPITP_ONLY(gtm_fork_n_core()); \
/* Reset active routine indicator before returning an error. \
* Caller would have done LIBYOTTADB_INIT before invoking this macro. Assert that. \
*/ \
assert(LYDB_RTN_NONE != TREF(libyottadb_active_rtn)); \
TREF(libyottadb_active_rtn) = LYDB_RTN_NONE; \
return; \
} \
/* We are in threaded mode but running an unthreaded command in the main work thread which \
* is allowed. In that case just fall out (verified). \
*/ \
} else \
noThreadAPI_active = TRUE; \
} MBEND

/* Variant of VERIFY_NON_THREADED_API macro that does a "return" but with a NULL pointer value */
#define VERIFY_NON_THREADED_API_RETNULL \
MBSTART { /* If threaded API but in worker thread, that is OK */ \
GBLREF boolean_t noThreadAPI_active; \
GBLREF boolean_t simpleThreadAPI_active; \
GBLREF stm_workq *stmWorkQueue[]; \
if (simpleThreadAPI_active) \
{ \
if (!IS_STAPI_WORKER_THREAD) \
{ \
SETUP_GENERIC_ERROR_4PARMS(ERR_INVAPIMODE, THREADED_STR_LEN, THREADED_STR, \
UNTHREADED_STR_LEN, UNTHREADED_STR); \
DBGAPITP_ONLY(gtm_fork_n_core()); \
/* Reset active routine indicator before returning an error. \
* Caller would have done LIBYOTTADB_INIT before invoking this macro. Assert that. \
*/ \
assert(LYDB_RTN_NONE != TREF(libyottadb_active_rtn)); \
TREF(libyottadb_active_rtn) = LYDB_RTN_NONE; \
return NULL; \
} \
/* We are in threaded mode but running an unthreaded command in the main work thread which \
* is allowed. In that case just fall out (verified). \
*/ \
} else \
noThreadAPI_active = TRUE; \
} MBEND

/* Variant of VERIFY_NON_THREADED_API macro that does a "return" but without resetting TREF(libyottadb_active_rtn).
* Called by functions that do not do LIBYOTTADB_INIT but do call VERIFY_NON_THREADED_API* macro.
*/
#define VERIFY_NON_THREADED_API_DO_NOT_SHUTOFF_ACTIVE_RTN \
MBSTART { /* If threaded API but in worker thread, that is OK */ \
GBLREF boolean_t noThreadAPI_active; \
GBLREF boolean_t simpleThreadAPI_active; \
GBLREF stm_workq *stmWorkQueue[]; \
if (simpleThreadAPI_active) \
{ \
if (!IS_STAPI_WORKER_THREAD) \
{ \
SETUP_GENERIC_ERROR_4PARMS(ERR_INVAPIMODE, THREADED_STR_LEN, THREADED_STR, \
UNTHREADED_STR_LEN, UNTHREADED_STR); \
DBGAPITP_ONLY(gtm_fork_n_core()); \
return YDB_ERR_INVAPIMODE; \
} \
/* We are in threaded mode but running an unthreaded command in the main work thread which \
* is allowed. In that case just fall out (verified). \
Expand Down
40 changes: 40 additions & 0 deletions sr_unix/ydb_ci.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/****************************************************************
* *
* Copyright (c) 2018 YottaDB LLC. and/or its subsidiaries. *
* All rights reserved. *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/

#include "mdef.h"

#include <stdarg.h>

#include "libyottadb_int.h"
#include "gtmci.h"

/* Simple YottaDB wrapper to do a call-in. Does name lookup on each call whereas "ydb_cip" does not. */
int ydb_ci(const char *c_rtn_name, ...)
{
va_list var;
int retval;
DCL_THREADGBL_ACCESS;

SETUP_THREADGBL_ACCESS;
/* Do not use LIBYOTTADB_INIT to avoid unnecessary SIMPLEAPINEST errors. Instead call LIBYOTTADB_RUNTIME_CHECK macro. */
LIBYOTTADB_RUNTIME_CHECK((int)); /* Note: macro could return from this function in case of errors */
VERIFY_NON_THREADED_API_DO_NOT_SHUTOFF_ACTIVE_RTN; /* Need to call this version of VERIFY_NON_THREADED_API macro
* since LIBYOTTADB_INIT was not called.
*/
/* "ydb_ci_exec" already sets up a condition handler "gtmci_ch" so we do not do an
* ESTABLISH_RET of ydb_simpleapi_ch here like is done for other SimpleAPI function calls.
*/
VAR_START(var, c_rtn_name);
/* Note: "va_end(var)" done inside "ydb_ci_exec" */
retval = ydb_ci_exec(c_rtn_name, NULL, FALSE, var, FALSE);
return retval;
}
42 changes: 42 additions & 0 deletions sr_unix/ydb_cip.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/****************************************************************
* *
* Copyright (c) 2018 YottaDB LLC. and/or its subsidiaries. *
* All rights reserved. *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/

#include "mdef.h"

#include <stdarg.h>

#include "libyottadb_int.h"
#include "gtmci.h"

/* Fast path YottaDB wrapper to do a call-in.
* Adds a struct parm that contains name resolution info after first call to speed up dispatching.
*/
int ydb_cip(ci_name_descriptor* ci_info, ...)
{
va_list var;
int retval;
DCL_THREADGBL_ACCESS;

SETUP_THREADGBL_ACCESS;
/* Do not use LIBYOTTADB_INIT to avoid unnecessary SIMPLEAPINEST errors. Instead call LIBYOTTADB_RUNTIME_CHECK macro. */
LIBYOTTADB_RUNTIME_CHECK((int)); /* Note: macro could return from this function in case of errors */
VERIFY_NON_THREADED_API_DO_NOT_SHUTOFF_ACTIVE_RTN; /* Need to call this version of VERIFY_NON_THREADED_API macro
* since LIBYOTTADB_INIT was not called.
*/
/* "ydb_ci_exec" already sets up a condition handler "gtmci_ch" so we do not do an
* ESTABLISH_RET of ydb_simpleapi_ch here like is done for other SimpleAPI function calls.
*/
VAR_START(var, ci_info);
/* Note: "va_end(var)" done inside "ydb_ci_exec" */
retval = ydb_ci_exec(ci_info->rtn_name.address, ci_info->handle, TRUE, var, FALSE);
return retval;
}
5 changes: 4 additions & 1 deletion sr_unix/ydb_cip_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,14 @@ int ydb_cip_helper(int calltyp, ci_name_descriptor *ci_info, va_list *var)
SETUP_THREADGBL_ACCESS;
/* Verify entry conditions, make sure YDB CI environment is up etc. */
assert((LYDB_RTN_YDB_CI == calltyp) || (LYDB_RTN_YDB_CIP == calltyp));
/* Need to call VERIFY_THREADED_API before LIBYOTTADB_INIT.
* Moving this to after LIBYOTTADB_INIT implies LIBYOTTADB_DONE would not be done in case of INVAPIMODE error.
*/
VERIFY_THREADED_API((int));
LIBYOTTADB_INIT(calltyp, (int)); /* Note: macro could "return" from this function in case of errors */
assert(0 == TREF(sapi_mstrs_for_gc_indx)); /* previously unused entries should have been cleared by that
* corresponding ydb_*_s() call.
*/
VERIFY_THREADED_API((int));
ESTABLISH_NORET(ydb_simpleapi_ch, error_encountered);
if (error_encountered)
{
Expand Down
2 changes: 1 addition & 1 deletion sr_unix/ydb_free.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void ydb_free(void *ptr)
assert(0 == TREF(sapi_mstrs_for_gc_indx)); /* Previously unused entries should have been cleared by that
* corresponding ydb_*_s() call.
*/
VERIFY_NON_THREADED_API;
VERIFY_NON_THREADED_API_NORETVAL;
ESTABLISH_NORET(ydb_simpleapi_ch, error_encountered);
if (error_encountered)
{ /* Some error occurred - just return to the caller ($ZSTATUS is set) */
Expand Down
5 changes: 3 additions & 2 deletions sr_unix/ydb_hiber_start.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
#include "libyottadb_int.h"
#include "libydberrors.h"

#ifdef DEBUG
GBLREF boolean_t simpleThreadAPI_active;
#endif

/* Simple YottaDB wrapper for gtm_hiber_start() */
int ydb_hiber_start(unsigned long long sleep_nsec)
Expand All @@ -42,8 +44,7 @@ int ydb_hiber_start(unsigned long long sleep_nsec)
return -(TREF(ydb_error_code));
}
ISSUE_TIME2LONG_ERROR_IF_NEEDED(sleep_nsec);
if (simpleThreadAPI_active)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_NOTSUPSTAPI, 2, RTS_ERROR_LITERAL("ydb_hiber_start()"));
assert(!simpleThreadAPI_active); /* or else an INVAPIMODE error would have been issued in VERIFY_NON_THREADED_API */
assert(MAXPOSINT4 >= (sleep_nsec / NANOSECS_IN_MSEC)); /* Or else a TIME2LONG error would have been issued above */
sleep_msec = (sleep_nsec / NANOSECS_IN_MSEC);
sleepms = (int)sleep_msec;
Expand Down
5 changes: 3 additions & 2 deletions sr_unix/ydb_hiber_start_wait_any.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
#include "libyottadb_int.h"
#include "libydberrors.h"

#ifdef DEBUG
GBLREF boolean_t simpleThreadAPI_active;
#endif

/* Simple YottaDB wrapper for gtm_hiber_start_wait_any() */
int ydb_hiber_start_wait_any(unsigned long long sleep_nsec)
Expand All @@ -41,8 +43,7 @@ int ydb_hiber_start_wait_any(unsigned long long sleep_nsec)
return -(TREF(ydb_error_code));
}
ISSUE_TIME2LONG_ERROR_IF_NEEDED(sleep_nsec);
if (simpleThreadAPI_active)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_NOTSUPSTAPI, 2, RTS_ERROR_LITERAL("ydb_hiber_startwaut_any()"));
assert(!simpleThreadAPI_active); /* or else an INVAPIMODE error would have been issued in VERIFY_NON_THREADED_API */
assert(MAXPOSINT4 >= (sleep_nsec / NANOSECS_IN_MSEC)); /* Or else a TIME2LONG error would have been issued above */
sleep_msec = (sleep_nsec / NANOSECS_IN_MSEC);
sleepms = (int)sleep_msec;
Expand Down
2 changes: 1 addition & 1 deletion sr_unix/ydb_malloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ void *ydb_malloc(size_t size)
assert(0 == TREF(sapi_mstrs_for_gc_indx)); /* Previously unused entries should have been cleared by that
* corresponding ydb_*_s() call.
*/
VERIFY_NON_THREADED_API;
VERIFY_NON_THREADED_API_RETNULL;
ESTABLISH_NORET(ydb_simpleapi_ch, error_encountered);
if (error_encountered)
{ /* Some error occurred - return NULL to the caller ($ZSTATUS is set) */
Expand Down
2 changes: 1 addition & 1 deletion sr_unix/ydb_timer_cancel.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void ydb_timer_cancel(int timer_id)
assert(0 == TREF(sapi_mstrs_for_gc_indx)); /* Previously unused entries should have been cleared by that
* corresponding ydb_*_s() call.
*/
VERIFY_NON_THREADED_API;
VERIFY_NON_THREADED_API_NORETVAL;
ESTABLISH_NORET(ydb_simpleapi_ch, error_encountered);
if (error_encountered)
{ /* Some error occurred - just return to the caller ($ZSTATUS is set) */
Expand Down
13 changes: 8 additions & 5 deletions sr_unix/ydb_tp_s_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,19 @@ int ydb_tp_s_common(libyottadb_routines lydbrtn,
assert((LYDB_RTN_TP == lydbrtn)
|| (LYDB_RTN_TP_START == lydbrtn) || (LYDB_RTN_TP_COMMIT == lydbrtn)
|| (LYDB_RTN_TP_RESTART == lydbrtn) || (LYDB_RTN_TP_ROLLBACK == lydbrtn));
/* Need to call VERIFY_THREADED_API before LIBYOTTADB_INIT.
* Moving this to after LIBYOTTADB_INIT implies LIBYOTTADB_DONE would not be done in case of INVAPIMODE error.
*/
if (LYDB_RTN_TP != lydbrtn)
{ /* We have been called via the threaded interface so verify we are in a threaded environment */
VERIFY_THREADED_API((int));
}
/* Verify entry conditions, make sure YDB CI environment is up etc. */
LIBYOTTADB_INIT(lydbrtn, (int)); /* Note: macro could "return" from this function in case of errors */
assert(0 == TREF(sapi_mstrs_for_gc_indx)); /* previously unused entries should have been cleared by that
* corresponding ydb_*_s() call.
*/

if (LYDB_RTN_TP != lydbrtn)
{ /* We have been called via the threaded interface so verify we are in a threaded environment */
VERIFY_THREADED_API((int));
} else
if (LYDB_RTN_TP == lydbrtn)
{ /* We have been called as non-threaded so verify we are not threaded */
VERIFY_NON_THREADED_API;
}
Expand Down

0 comments on commit 4c4ca46

Please sign in to comment.