The Pth 1.4.1 "Hard System Call Mapping" scheme makes use of the syscall(2) function to wrap system calls. The Pth doc acknowledges that this may hit conflicts with the vendor's header files, but there is another more fundamental problem as well:
This approach assumes that the C library interface for a function is the same as its underlying syscall() interface, in terms of arguments and return values. In most cases this is true, but for some calls on some OSes it is not. For example on SCO's UnixWare/Open UNIX OS, both system() and waitpid() have a system call interface that uses multiple return values via assembly language registers. These return values are mapped to the POSIX signature by an assembly code layer within the C library. Consequently, calling these functions in the C library and calling them via syscall() do not produce the same results; you simply can't use syscall() for them from application C code. Thus, the Pth hard wrapper mechanism breaks down. An alternative approach is to use the dlsym(RTLD_NEXT) feature, which is specified in the Unix 98 standard and is available on many current-day systems. This is a more robust way of coding wrapper functions for system calls, since it's designed for that purpose. Note that for this to work you have to use the dynamically linked Pth libpthread, so that the "real" definition can be found in a downstream library (usually libc). Here are the changes to use dlsym. They are to pth_lib.c and pth_syscall.c. The changes are mostly in one place, due to good encapsulation provided by the pth_sc macro. --- pth_lib.c..orig Sun Jan 27 06:03:40 2002 +++ pth_lib.c Tue Oct 15 13:15:04 2002 @@ -47,6 +47,11 @@ int pth_init(void) { pth_attr_t t_attr; +#if defined(__USLC__) || defined(__svr4__) +#if PTH_SYSCALL_HARD + extern int pth_sys_func_table_init(void); +#endif +#endif /* support for implicit initialization calls and to prevent multiple explict initialization, too */ @@ -55,6 +60,13 @@ else pth_initialized = TRUE; +#if defined(__USLC__) || defined(__svr4__) +#if PTH_SYSCALL_HARD + if (pth_sys_func_table_init() == FALSE) + return FALSE; +#endif +#endif + pth_debug1("pth_init: enter"); /* initialize the scheduler */ --- pth_syscall.c..orig Sun Jan 27 06:03:41 2002 +++ pth_syscall.c Tue Oct 15 11:58:31 2002 @@ -36,13 +36,78 @@ #ifdef HAVE_SYS_SOCKETCALL_H #include <sys/socketcall.h> #endif +#if defined(__USLC__) || defined(__svr4__) +int pth_sys_func_table_init(void); +typedef int (*pth_sys_func_t)(); +typedef struct pth_sys_func_table_t { + char* name; + pth_sys_func_t addr; +} pth_sys_func_table_t; +extern pth_sys_func_table_t pth_sys_func_table[]; +#define PTH_SFT_read 0 +#define PTH_SFT_readv 1 +#define PTH_SFT_write 2 +#define PTH_SFT_writev 3 +#define PTH_SFT_select 4 +#define PTH_SFT_connect 5 +#define PTH_SFT_accept 6 +#define PTH_SFT_recvfrom 7 +#define PTH_SFT_sendto 8 +#define PTH_SFT_fork 9 +#define PTH_SFT_sigprocmask 10 +#define PTH_SFT_waitpid 11 +#define PTH_SFT__xconnect 12 +#define PTH_SFT__xaccept 13 +#define PTH_SFT__xrecvfrom 14 +#define PTH_SFT__xsendto 15 +#define pth_sc(func) (*pth_sys_func_table[PTH_SFT_##func].addr) +#else #define pth_sc(func) PTH_SC_##func +#endif #else #define pth_sc(func) func #endif #endif /* cpp */ +#if defined(__USLC__) || defined(__svr4__) +#if PTH_SYSCALL_HARD +#include <dlfcn.h> + +pth_sys_func_table_t pth_sys_func_table[] = { + // this order must match the macro values above + { "read", NULL }, + { "readv", NULL }, + { "write", NULL }, + { "writev", NULL }, + { "select", NULL }, + { "connect", NULL }, + { "accept", NULL }, + { "recvfrom", NULL }, + { "sendto", NULL }, + { "fork", NULL }, + { "sigprocmask", NULL }, + { "waitpid", NULL }, + { "_xconnect", NULL }, + { "_xaccept", NULL }, + { "_xrecvfrom", NULL }, + { "_xsendto", NULL }, + { NULL, NULL }, +}; + +int pth_sys_func_table_init(void) { + pth_sys_func_table_t* p_sft = pth_sys_func_table; + while (p_sft->name != NULL) { + p_sft->addr = (pth_sys_func_t) dlsym(RTLD_NEXT, p_sft->name); + // Note the above dlsym() may return NULL, + // e.g. the networking calls when libsocket is not linked. + p_sft++; + } + return TRUE; +} +#endif +#endif + /* some exported variables for object layer checks */ int pth_syscall_soft = PTH_SYSCALL_SOFT; int pth_syscall_hard = PTH_SYSCALL_HARD; The "defined(__USLC__) || defined(__svr4__)" test is to activate it for SCO UNIX systems; if this were to be incorporated in mainline Pth, this would have to be replaced with a macro test driven from the configure process, since the syscall() method needs to be retained as an option for systems that don't have dlsym(RTLD_NEXT) and for static links. Jonathan Schilling SCO/Caldera [EMAIL PROTECTED] ______________________________________________________________________ GNU Portable Threads (Pth) http://www.gnu.org/software/pth/ User Support Mailing List [EMAIL PROTECTED] Automated List Manager (Majordomo) [EMAIL PROTECTED]