diff options
author | Werner Koch <[email protected]> | 2014-08-25 14:33:09 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2014-08-25 14:37:46 +0000 |
commit | fc651665010056e6184e8514e5c5436427d7052d (patch) | |
tree | 08156e7155986a560c06812748090d64bc654017 /src | |
parent | Remove GnuPG specific code. (diff) | |
download | libgpg-error-fc651665010056e6184e8514e5c5436427d7052d.tar.gz libgpg-error-fc651665010056e6184e8514e5c5436427d7052d.zip |
Replace locking code in estream functions.
* src/posix-lock.c: Add weak program for pthread_mutex_trylock.
(_gpgrt_lock_trylock): New.
* src/w32-lock.c (_gpgrt_lock_init): Add missing return statement.
(_gpgrt_lock_trylock): New.
* src/visibility.c (gpgrt_set_syscall_clamp): New.
(gpgrt_lock_trylock): New.
(gpgrt_vsnprintf): Fix symbol name.
* src/init.c (DllMain): Mark unused arg.
* src/estream.c: Replace npth mutexes by our own locks. Replace yeild
macro by _gpgrt_yield.
(pre_syscall_func, post_syscall_func): New.
(do_deinit): Clear both new vars.
(es_func_fd_read, es_func_fd_write): Call pre and post syscall
functions instead of the former SYSCALL macros.
(es_func_w32_read, es_func_w32_write): Ditto.
(es_func_fd_seek, es_func_w32_seek, es_func_fp_read)
(es_func_fp_write, es_func_fp_seek, es_func_fp_destroy): Bracket
syscalls with the pre- and post-syscall fucntions.
(do_npth_read, do_npth_write): Remove.
(_gpgrt_es_init): Remove call to mutex init. It is now statically
initialized.
(_gpgrt_set_syscall_clamp): New.
(es_create): Destroy stream lock on error.
(do_close): Destroy stream lock.
Diffstat (limited to 'src')
-rw-r--r-- | src/estream.c | 228 | ||||
-rw-r--r-- | src/gpg-error.def.in | 150 | ||||
-rw-r--r-- | src/gpg-error.h.in | 4 | ||||
-rw-r--r-- | src/gpg-error.vers | 5 | ||||
-rw-r--r-- | src/gpgrt-int.h | 2 | ||||
-rw-r--r-- | src/init.c | 1 | ||||
-rw-r--r-- | src/posix-lock.c | 24 | ||||
-rw-r--r-- | src/visibility.c | 17 | ||||
-rw-r--r-- | src/visibility.h | 4 | ||||
-rw-r--r-- | src/w32-lock.c | 25 |
10 files changed, 251 insertions, 209 deletions
diff --git a/src/estream.c b/src/estream.c index d34e669..cf3067b 100644 --- a/src/estream.c +++ b/src/estream.c @@ -87,15 +87,6 @@ #endif -#ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth. */ -# undef HAVE_NPTH -# undef USE_NPTH -#endif - -#ifdef HAVE_NPTH -# include <npth.h> -#endif - #include "gpgrt-int.h" #include "estream-printf.h" @@ -144,19 +135,6 @@ typedef void (*func_free_t) (void *mem); #define BUFFER_UNREAD_SIZE 16 -/* Primitive system I/O. */ - -#ifdef USE_NPTH -# define ESTREAM_SYS_READ do_npth_read -# define ESTREAM_SYS_WRITE do_npth_write -# define ESTREAM_SYS_YIELD() npth_usleep (0) -#else -# define ESTREAM_SYS_READ read -# define ESTREAM_SYS_WRITE write -# define ESTREAM_SYS_YIELD() do { } while (0) -#endif - - /* A linked list to hold notification functions. */ struct notify_list_s { @@ -181,9 +159,7 @@ struct _gpgrt_stream_internal unsigned char buffer[BUFFER_BLOCK_SIZE]; unsigned char unread_buffer[BUFFER_UNREAD_SIZE]; -#ifdef USE_NPTH - npth_mutex_t lock; /* Lock. */ -#endif + gpgrt_lock_t lock; /* Lock. */ void *cookie; /* Cookie. */ void *opaque; /* Opaque data. */ @@ -220,16 +196,16 @@ struct estream_list_s }; typedef struct estream_list_s *estream_list_t; static estream_list_t estream_list; +/* A lock object for the estream list and the custom_std_fds array. */ +GPGRT_LOCK_DEFINE (estream_list_lock); /* File descriptors registered to be used as the standard file handles. */ static int custom_std_fds[3]; static unsigned char custom_std_fds_valid[3]; -/* A lock object for the estream list and the custom_std_fds array. */ -#ifdef USE_NPTH -static npth_mutex_t estream_list_lock; -#endif - +/* Functions called before and after blocking syscalls. */ +static void (*pre_syscall_func)(void); +static void (*post_syscall_func)(void); /* Error code replacements. */ #ifndef EOPNOTSUPP @@ -356,114 +332,77 @@ memrchr (const void *buffer, int c, size_t n) static int init_stream_lock (estream_t _GPGRT__RESTRICT stream) { -#ifdef USE_NPTH int rc; if (!stream->intern->samethread) { dbg_lock_1 ("enter init_stream_lock for %p\n", stream); - rc = npth_mutex_init (&stream->intern->lock, NULL); + memset (&stream->intern->lock, 0 , sizeof stream->intern->lock); + rc = _gpgrt_lock_init (&stream->intern->lock); dbg_lock_2 ("leave init_stream_lock for %p: rc=%d\n", stream, rc); } else rc = 0; return rc; -#else - (void)stream; - return 0; -#endif } static void lock_stream (estream_t _GPGRT__RESTRICT stream) { -#ifdef USE_NPTH if (!stream->intern->samethread) { dbg_lock_1 ("enter lock_stream for %p\n", stream); - npth_mutex_lock (&stream->intern->lock); + _gpgrt_lock_lock (&stream->intern->lock); dbg_lock_1 ("leave lock_stream for %p\n", stream); } -#else - (void)stream; -#endif } static int trylock_stream (estream_t _GPGRT__RESTRICT stream) { -#ifdef USE_NPTH int rc; if (!stream->intern->samethread) { dbg_lock_1 ("enter trylock_stream for %p\n", stream); - rc = npth_mutex_trylock (&stream->intern->lock)? 0 : -1; + rc = _gpgrt_lock_trylock (&stream->intern->lock)? 0 : -1; dbg_lock_2 ("leave trylock_stream for %p: rc=%d\n", stream, rc); } else rc = 0; return rc; -#else - (void)stream; - return 0; -#endif } static void unlock_stream (estream_t _GPGRT__RESTRICT stream) { -#ifdef USE_NPTH if (!stream->intern->samethread) { dbg_lock_1 ("enter unlock_stream for %p\n", stream); - npth_mutex_unlock (&stream->intern->lock); + _gpgrt_lock_unlock (&stream->intern->lock); dbg_lock_1 ("leave unlock_stream for %p\n", stream); } -#else - (void)stream; -#endif -} - - -static int -init_list_lock (void) -{ -#ifdef USE_NPTH - int rc; - - dbg_lock_0 ("enter init_list_lock\n"); - rc = npth_mutex_init (&estream_list_lock, NULL); - dbg_lock_1 ("leave init_list_lock: rc=%d\n", rc); - return rc; -#else - return 0; -#endif } static void lock_list (void) { -#ifdef USE_NPTH dbg_lock_0 ("enter lock_list\n"); - npth_mutex_lock (&estream_list_lock); + _gpgrt_lock_lock (&estream_list_lock); dbg_lock_0 ("leave lock_list\n"); -#endif } static void unlock_list (void) { -#ifdef USE_NPTH dbg_lock_0 ("enter unlock_list\n"); - npth_mutex_unlock (&estream_list_lock); + _gpgrt_lock_unlock (&estream_list_lock); dbg_lock_0 ("leave unlock_list\n"); -#endif } @@ -537,45 +476,6 @@ do_list_remove (estream_t stream, int with_locked_list) -/* - * I/O Helper - * - * Unfortunately our Pth emulation for Windows expects system handles - * for npth_read and npth_write. We use a simple approach to fix this: - * If the function returns an error we fall back to a vanilla read or - * write, assuming that we do I/O on a plain file where the operation - * can't block. FIXME: Is this still needed for npth? - */ -#ifdef USE_NPTH -static int -do_npth_read (int fd, void *buffer, size_t size) -{ -# ifdef HAVE_W32_SYSTEM - int rc = npth_read (fd, buffer, size); - if (rc == -1 && errno == EINVAL) - rc = read (fd, buffer, size); - return rc; -# else /*!HAVE_W32_SYSTEM*/ - return npth_read (fd, buffer, size); -# endif /* !HAVE_W32_SYSTEM*/ -} - -static int -do_npth_write (int fd, const void *buffer, size_t size) -{ -# ifdef HAVE_W32_SYSTEM - int rc = npth_write (fd, buffer, size); - if (rc == -1 && errno == EINVAL) - rc = write (fd, buffer, size); - return rc; -# else /*!HAVE_W32_SYSTEM*/ - return npth_write (fd, buffer, size); -# endif /* !HAVE_W32_SYSTEM*/ -} -#endif /*USE_NPTH*/ - - - static void do_deinit (void) { @@ -589,6 +489,10 @@ do_deinit (void) list and the streams with possible undesirable effects. Given that we don't close the stream either, it should not matter that we keep the list and let the OS clean it up at process end. */ + + /* Reset the syscall clamp. */ + pre_syscall_func = NULL; + post_syscall_func = NULL; } @@ -603,13 +507,29 @@ _gpgrt_es_init (void) if (!initialized) { - if (!init_list_lock ()) - initialized = 1; + initialized = 1; atexit (do_deinit); } return 0; } +/* Register the syscall clamp. These two functions are called + immediately before and after a possible blocking system call. This + should be used before any I/O happens. The function is commonly + used with the nPth library: + + gpgrt_set_syscall_clamp (npth_protect, npth_unprotect); + + These functions may not modify ERRNO. +*/ +void +_gpgrt_set_syscall_clamp (void (*pre)(void), void (*post)(void)) +{ + pre_syscall_func = pre; + post_syscall_func = post; +} + + /* @@ -973,14 +893,20 @@ es_func_fd_read (void *cookie, void *buffer, size_t size) if (IS_INVALID_FD (file_cookie->fd)) { - ESTREAM_SYS_YIELD (); + _gpgrt_yield (); bytes_read = 0; } else { + if (pre_syscall_func) + pre_syscall_func (); do - bytes_read = ESTREAM_SYS_READ (file_cookie->fd, buffer, size); + { + bytes_read = read (file_cookie->fd, buffer, size); + } while (bytes_read == -1 && errno == EINTR); + if (post_syscall_func) + post_syscall_func (); } return bytes_read; @@ -995,14 +921,20 @@ es_func_fd_write (void *cookie, const void *buffer, size_t size) if (IS_INVALID_FD (file_cookie->fd)) { - ESTREAM_SYS_YIELD (); + _gpgrt_yield (); bytes_written = size; /* Yeah: Success writing to the bit bucket. */ } else { + if (pre_syscall_func) + pre_syscall_func (); do - bytes_written = ESTREAM_SYS_WRITE (file_cookie->fd, buffer, size); + { + bytes_written = write (file_cookie->fd, buffer, size); + } while (bytes_written == -1 && errno == EINTR); + if (post_syscall_func) + post_syscall_func (); } return bytes_written; @@ -1023,7 +955,11 @@ es_func_fd_seek (void *cookie, off_t *offset, int whence) } else { + if (pre_syscall_func) + pre_syscall_func (); offset_new = lseek (file_cookie->fd, *offset, whence); + if (post_syscall_func) + post_syscall_func (); if (offset_new == -1) err = -1; else @@ -1116,18 +1052,15 @@ es_func_w32_read (void *cookie, void *buffer, size_t size) if (w32_cookie->hd == INVALID_HANDLE_VALUE) { - ESTREAM_SYS_YIELD (); + _gpgrt_yield (); bytes_read = 0; } else { + if (pre_syscall_func) + pre_syscall_func (); do { -#ifdef USE_NPTH - /* Note: Our pth_read actually uses HANDLE! - FIXME: Check whether this is the case for npth. */ - bytes_read = npth_read ((int)w32_cookie->hd, buffer, size); -#else DWORD nread, ec; if (!ReadFile (w32_cookie->hd, buffer, size, &nread, NULL)) @@ -1143,9 +1076,10 @@ es_func_w32_read (void *cookie, void *buffer, size_t size) } else bytes_read = (int)nread; -#endif } while (bytes_read == -1 && errno == EINTR); + if (post_syscall_func) + post_syscall_func (); } return bytes_read; @@ -1160,17 +1094,15 @@ es_func_w32_write (void *cookie, const void *buffer, size_t size) if (w32_cookie->hd == INVALID_HANDLE_VALUE) { - ESTREAM_SYS_YIELD (); + _gpgrt_yield (); bytes_written = size; /* Yeah: Success writing to the bit bucket. */ } else { + if (pre_syscall_func) + pre_syscall_func (); do { -#ifdef USE_NPTH - /* Note: Our pth_write actually uses HANDLE! */ - bytes_written = npth_write ((int)w32_cookie->hd, buffer, size); -#else DWORD nwritten; if (!WriteFile (w32_cookie->hd, buffer, size, &nwritten, NULL)) @@ -1180,9 +1112,10 @@ es_func_w32_write (void *cookie, const void *buffer, size_t size) } else bytes_written = (int)nwritten; -#endif } while (bytes_written == -1 && errno == EINTR); + if (post_syscall_func) + post_syscall_func (); } return bytes_written; @@ -1225,11 +1158,17 @@ es_func_w32_seek (void *cookie, off_t *offset, int whence) #ifdef HAVE_W32CE_SYSTEM # warning need to use SetFilePointer #else + if (pre_syscall_func) + pre_syscall_func (); if (!SetFilePointerEx (w32_cookie->hd, distance, &newoff, method)) { _set_errno (map_w32_to_errno (GetLastError ())); + if (post_syscall_func) + post_syscall_func (); return -1; } + if (post_syscall_func) + post_syscall_func (); #endif *offset = (unsigned long long)newoff.QuadPart; return 0; @@ -1327,7 +1266,13 @@ es_func_fp_read (void *cookie, void *buffer, size_t size) ssize_t bytes_read; if (file_cookie->fp) - bytes_read = fread (buffer, 1, size, file_cookie->fp); + { + if (pre_syscall_func) + pre_syscall_func (); + bytes_read = fread (buffer, 1, size, file_cookie->fp); + if (post_syscall_func) + post_syscall_func (); + } else bytes_read = 0; if (!bytes_read && ferror (file_cookie->fp)) @@ -1344,6 +1289,8 @@ es_func_fp_write (void *cookie, const void *buffer, size_t size) if (file_cookie->fp) { + if (pre_syscall_func) + pre_syscall_func (); #ifdef HAVE_W32_SYSTEM /* Using an fwrite to stdout connected to the console fails with the error "Not enough space" for an fwrite size of >= 52KB @@ -1365,6 +1312,8 @@ es_func_fp_write (void *cookie, const void *buffer, size_t size) bytes_written = fwrite (buffer, 1, size, file_cookie->fp); #endif fflush (file_cookie->fp); + if (post_syscall_func) + post_syscall_func (); } else bytes_written = size; /* Successfully written to the bit bucket. */ @@ -1386,14 +1335,20 @@ es_func_fp_seek (void *cookie, off_t *offset, int whence) return -1; } + if (pre_syscall_func) + pre_syscall_func (); if ( fseek (file_cookie->fp, (long int)*offset, whence) ) { /* fprintf (stderr, "\nfseek failed: errno=%d (%s)\n", */ /* errno,strerror (errno)); */ + if (post_syscall_func) + post_syscall_func (); return -1; } offset_new = ftell (file_cookie->fp); + if (post_syscall_func) + post_syscall_func (); if (offset_new == -1) { /* fprintf (stderr, "\nftell failed: errno=%d (%s)\n", */ @@ -1415,7 +1370,11 @@ es_func_fp_destroy (void *cookie) { if (fp_cookie->fp) { + if (pre_syscall_func) + pre_syscall_func (); fflush (fp_cookie->fp); + if (post_syscall_func) + post_syscall_func (); err = fp_cookie->no_close? 0 : fclose (fp_cookie->fp); } else @@ -1865,6 +1824,8 @@ es_create (estream_t *stream, void *cookie, es_syshd_t *syshd, if (stream_new) { es_deinitialize (stream_new); + _gpgrt_lock_destroy (&stream_new->intern->lock); + mem_free (stream_new->intern); mem_free (stream_new); } } @@ -1892,6 +1853,7 @@ do_close (estream_t stream, int with_locked_list) stream->intern->onclose = tmp; } err = es_deinitialize (stream); + _gpgrt_lock_destroy (&stream->intern->lock); mem_free (stream->intern); mem_free (stream); } diff --git a/src/gpg-error.def.in b/src/gpg-error.def.in index 7ccd05e..2b50962 100644 --- a/src/gpg-error.def.in +++ b/src/gpg-error.def.in @@ -54,79 +54,83 @@ EXPORTS gpgrt_lock_unlock @22 gpgrt_lock_destroy @23 gpgrt_yield @24 + gpgrt_lock_trylock @25 + + gpgrt_set_syscall_clamp @26 + + gpgrt_fopen @27 + gpgrt_mopen @28 + gpgrt_fopenmem @29 + gpgrt_fopenmem_init @30 + gpgrt_fdopen @31 + gpgrt_fdopen_nc @32 + gpgrt_sysopen @33 + gpgrt_sysopen_nc @34 + gpgrt_fpopen @35 + gpgrt_fpopen_nc @36 + gpgrt_freopen @37 + gpgrt_fopencookie @38 + gpgrt_fclose @39 + gpgrt_fclose_snatch @40 + gpgrt_onclose @41 + gpgrt_fileno @42 + gpgrt_fileno_unlocked @43 + gpgrt_syshd @44 + gpgrt_syshd_unlocked @45 + _gpgrt_set_std_fd @46 + _gpgrt_get_std_stream @47 + gpgrt_flockfile @48 + gpgrt_ftrylockfile @49 + gpgrt_funlockfile @50 + gpgrt_feof @51 + gpgrt_feof_unlocked @52 + gpgrt_ferror @53 + gpgrt_ferror_unlocked @54 + gpgrt_clearerr @55 + gpgrt_clearerr_unlocked @56 + gpgrt_fflush @57 + gpgrt_fseek @58 + gpgrt_fseeko @59 + gpgrt_ftell @60 + gpgrt_ftello @61 + gpgrt_rewind @62 + gpgrt_fgetc @63 + _gpgrt_getc_underflow @64 + gpgrt_fputc @65 + _gpgrt_putc_overflow @66 + gpgrt_ungetc @67 + gpgrt_read @68 + gpgrt_write @69 + gpgrt_write_sanitized @70 + gpgrt_write_hexstring @71 + gpgrt_fread @72 + gpgrt_fwrite @73 + gpgrt_fgets @74 + gpgrt_fputs @75 + gpgrt_fputs_unlocked @76 + gpgrt_getline @77 + gpgrt_read_line @78 + gpgrt_free @79 + gpgrt_fprintf @80 + gpgrt_fprintf_unlocked @81 + gpgrt_printf @82 + gpgrt_printf_unlocked @83 + gpgrt_vfprintf @84 + gpgrt_vfprintf_unlocked @85 + gpgrt_setvbuf @86 + gpgrt_setbuf @87 + gpgrt_set_binary @88 + gpgrt_tmpfile @89 + gpgrt_opaque_set @90 + gpgrt_opaque_get @91 + gpgrt_fname_set @92 + gpgrt_fname_get @93 + gpgrt_asprintf @94 + gpgrt_vasprintf @95 + gpgrt_bsprintf @96 + gpgrt_vbsprintf @97 + gpgrt_snprintf @98 + gpgrt_vsnprintf @99 - gpgrt_fopen @25 - gpgrt_mopen @26 - gpgrt_fopenmem @27 - gpgrt_fopenmem_init @28 - gpgrt_fdopen @29 - gpgrt_fdopen_nc @30 - gpgrt_sysopen @31 - gpgrt_sysopen_nc @32 - gpgrt_fpopen @33 - gpgrt_fpopen_nc @34 - gpgrt_freopen @35 - gpgrt_fopencookie @36 - gpgrt_fclose @37 - gpgrt_fclose_snatch @38 - gpgrt_onclose @39 - gpgrt_fileno @40 - gpgrt_fileno_unlocked @41 - gpgrt_syshd @42 - gpgrt_syshd_unlocked @43 - _gpgrt_set_std_stream @44 - _gpgrt_get_std_stream @45 - gpgrt_flockfile @46 - gpgrt_ftrylockfile @47 - gpgrt_funlockfile @48 - gpgrt_feof @49 - gpgrt_feof_unlocked @50 - gpgrt_ferror @51 - gpgrt_ferror_unlocked @52 - gpgrt_clearerr @53 - gpgrt_clearerr_unlocked @54 - gpgrt_fflush @55 - gpgrt_fseek @56 - gpgrt_fseeko @57 - gpgrt_ftell @58 - gpgrt_ftello @59 - gpgrt_rewind @60 - gpgrt_fgetc @61 - _gpgrt_getc_underflow @62 - gpgrt_fputc @63 - _gpgrt_putc_overflow @64 - gpgrt_ungetc @65 - gpgrt_read @66 - gpgrt_write @67 - gpgrt_write_sanitized @68 - gpgrt_write_hexstring @69 - gpgrt_fread @70 - gpgrt_fwrite @71 - gpgrt_fgets @72 - gpgrt_fputs @73 - gpgrt_fputs_unlocked @74 - gpgrt_getline @75 - gpgrt_read_line @76 - gpgrt_free @77 - gpgrt_fprintf @78 - gpgrt_fprintf_unlocked @79 - gpgrt_printf @80 - gpgrt_printf_unlocked @81 - gpgrt_vfprintf @82 - gpgrt_vfprintf_unlocked @83 - gpgrt_setvbuf @84 - gpgrt_setbuf @85 - gpgrt_set_binary @86 - gpgrt_tmpfile @87 - gpgrt_opaque_set @88 - gpgrt_opaque_get @89 - gpgrt_fname_set @90 - gpgrt_fname_get @91 - gpgrt_asprintf @92 - gpgrt_vasprintf @93 - gpgrt_bsprintf @94 - gpgrt_vbsprintf @95 - gpgrt_snprintf @96 - gpgrt_vsnprintf @97 ;; end of file with public symbols for Windows. diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in index 20139ee..993e83b 100644 --- a/src/gpg-error.h.in +++ b/src/gpg-error.h.in @@ -177,6 +177,9 @@ gpg_error_t gpg_err_init (void) _GPG_ERR_CONSTRUCTOR; #define GPG_ERR_INITIALIZED 1 #endif +/* Register blocking system I/O clamping functions. */ +void gpgrt_set_syscall_clamp (void (*pre)(void), void (*post)(void)); + /* See the source on how to use the deinit function; it is usually not required. */ void gpg_err_deinit (int mode); @@ -313,6 +316,7 @@ gpg_error_from_syserror (void) before passing it to gpgrt_lock_init. */ gpg_err_code_t gpgrt_lock_init (gpgrt_lock_t *lockhd); gpg_err_code_t gpgrt_lock_lock (gpgrt_lock_t *lockhd); +gpg_err_code_t gpgrt_lock_trylock (gpgrt_lock_t *lockhd); gpg_err_code_t gpgrt_lock_unlock (gpgrt_lock_t *lockhd); gpg_err_code_t gpgrt_lock_destroy (gpgrt_lock_t *lockhd); diff --git a/src/gpg-error.vers b/src/gpg-error.vers index a4ff726..d07372e 100644 --- a/src/gpg-error.vers +++ b/src/gpg-error.vers @@ -36,6 +36,9 @@ GPG_ERROR_1.0 { gpgrt_lock_unlock; gpgrt_lock_destroy; gpgrt_yield; + gpgrt_lock_trylock; + + gpgrt_set_syscall_clamp; gpgrt_fopen; gpgrt_mopen; @@ -56,7 +59,7 @@ GPG_ERROR_1.0 { gpgrt_fileno_unlocked; gpgrt_syshd; gpgrt_syshd_unlocked; - _gpgrt_set_std_stream; + _gpgrt_set_std_fd; _gpgrt_get_std_stream; gpgrt_flockfile; gpgrt_ftrylockfile; diff --git a/src/gpgrt-int.h b/src/gpgrt-int.h index 5743781..025d781 100644 --- a/src/gpgrt-int.h +++ b/src/gpgrt-int.h @@ -36,6 +36,7 @@ const char *_gpg_error_check_version (const char *req_version); gpg_err_code_t _gpgrt_lock_init (gpgrt_lock_t *lockhd); gpg_err_code_t _gpgrt_lock_lock (gpgrt_lock_t *lockhd); +gpg_err_code_t _gpgrt_lock_trylock (gpgrt_lock_t *lockhd); gpg_err_code_t _gpgrt_lock_unlock (gpgrt_lock_t *lockhd); gpg_err_code_t _gpgrt_lock_destroy (gpgrt_lock_t *lockhd); gpg_err_code_t _gpgrt_yield (void); @@ -43,6 +44,7 @@ gpg_err_code_t _gpgrt_yield (void); /* Local prototypes for estream. */ int _gpgrt_es_init (void); +void _gpgrt_set_syscall_clamp (void (*pre)(void), void (*post)(void)); gpgrt_stream_t _gpgrt_fopen (const char *_GPGRT__RESTRICT path, const char *_GPGRT__RESTRICT mode); @@ -380,6 +380,7 @@ DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved) { struct tls_space_s *tls; (void)reserved; + (void)hinst; switch (reason) { diff --git a/src/posix-lock.c b/src/posix-lock.c index 22bb734..7f20347 100644 --- a/src/posix-lock.c +++ b/src/posix-lock.c @@ -52,6 +52,7 @@ # pragma weak pthread_cancel # pragma weak pthread_mutex_init # pragma weak pthread_mutex_lock +# pragma weak pthread_mutex_trylock # pragma weak pthread_mutex_unlock # pragma weak pthread_mutex_destroy # if ! PTHREAD_IN_USE_DETECTION_HARD @@ -172,6 +173,29 @@ _gpgrt_lock_lock (gpgrt_lock_t *lockhd) gpg_err_code_t +_gpgrt_lock_trylock (gpgrt_lock_t *lockhd) +{ + _gpgrt_lock_t *lock = get_lock_object (lockhd); + int rc; + +#if USE_POSIX_THREADS + if (use_pthread_p()) + { + rc = pthread_mutex_trylock (&lock->u.mtx); + if (rc) + rc = gpg_err_code_from_errno (rc); + } + else + rc = 0; /* Threads are not used. */ +#else /* Unknown thread system. */ + rc = GPG_ERR_NOT_IMPLEMENTED; +#endif /* Unknown thread system. */ + + return rc; +} + + +gpg_err_code_t _gpgrt_lock_unlock (gpgrt_lock_t *lockhd) { _gpgrt_lock_t *lock = get_lock_object (lockhd); diff --git a/src/visibility.c b/src/visibility.c index 811a5cf..67c5bfd 100644 --- a/src/visibility.c +++ b/src/visibility.c @@ -72,6 +72,13 @@ gpg_error_check_version (const char *req_version) return _gpg_error_check_version (req_version); } + +void +gpgrt_set_syscall_clamp (void (*pre)(void), void (*post)(void)) +{ + _gpgrt_set_syscall_clamp (pre, post); +} + gpg_err_code_t gpgrt_lock_init (gpgrt_lock_t *lockhd) @@ -86,6 +93,12 @@ gpgrt_lock_lock (gpgrt_lock_t *lockhd) } gpg_err_code_t +gpgrt_lock_trylock (gpgrt_lock_t *lockhd) +{ + return _gpgrt_lock_trylock (lockhd); +} + +gpg_err_code_t gpgrt_lock_unlock (gpgrt_lock_t *lockhd) { return _gpgrt_lock_unlock (lockhd); @@ -634,8 +647,8 @@ gpgrt_snprintf (char *buf, size_t bufsize, const char *format, ...) } int -gpgrt_estream_vsnprintf (char *buf, size_t bufsize, - const char *format, va_list arg_ptr) +gpgrt_vsnprintf (char *buf, size_t bufsize, + const char *format, va_list arg_ptr) { return _gpgrt_estream_vsnprintf (buf, bufsize, format, arg_ptr); } diff --git a/src/visibility.h b/src/visibility.h index 873ed5b..64a01a0 100644 --- a/src/visibility.h +++ b/src/visibility.h @@ -58,6 +58,7 @@ MARK_VISIBLE (gpgrt_lock_lock) MARK_VISIBLE (gpgrt_lock_unlock) MARK_VISIBLE (gpgrt_lock_destroy) MARK_VISIBLE (gpgrt_yield) +MARK_VISIBLE (gpgrt_lock_trylock) MARK_VISIBLE (gpgrt_fopen) MARK_VISIBLE (gpgrt_mopen) @@ -132,6 +133,7 @@ MARK_VISIBLE (gpgrt_bsprintf) MARK_VISIBLE (gpgrt_vbsprintf) MARK_VISIBLE (gpgrt_snprintf) MARK_VISIBLE (gpgrt_vsnprintf) +MARK_VISIBLE (gpgrt_set_syscall_clamp) #undef MARK_VISIBLE @@ -149,12 +151,14 @@ MARK_VISIBLE (gpgrt_vsnprintf) #define gpg_err_set_errno _gpgrt_USE_UNDERSCORED_FUNCTION #define gpg_error_check_version _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_set_syscall_clamp _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_lock_init _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_lock_lock _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_lock_unlock _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_lock_destroy _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_yield _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_lock_trylock _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_fopen _gpgrt_USE_UNDERSCORED_FUNCTION #define gpgrt_mopen _gpgrt_USE_UNDERSCORED_FUNCTION diff --git a/src/w32-lock.c b/src/w32-lock.c index 3aac1ae..8c086f9 100644 --- a/src/w32-lock.c +++ b/src/w32-lock.c @@ -72,6 +72,7 @@ _gpgrt_lock_init (gpgrt_lock_t *lockhd) InitializeCriticalSection (&lock->csec); lock->initdone = 1; + return 0; } @@ -106,6 +107,30 @@ _gpgrt_lock_lock (gpgrt_lock_t *lockhd) gpg_err_code_t +_gpgrt_lock_trylock (gpgrt_lock_t *lockhd) +{ + _gpgrt_lock_t *lock = get_lock_object (lockhd); + + if (!lock->initdone) + { + if (!InterlockedIncrement (&lock->started)) + { + gpgrt_lock_init (lockhd); + } + else + { + while (!lock->initdone) + Sleep (0); + } + } + + if (!TryEnterCriticalSection (&lock->csec)) + return GPG_ERR_EBUSY; + return 0; +} + + +gpg_err_code_t _gpgrt_lock_unlock (gpgrt_lock_t *lockhd) { _gpgrt_lock_t *lock = get_lock_object (lockhd); |