From 81d11c5e93a86f472c460be0be9b7a2c94551aec Mon Sep 17 00:00:00 2001 From: Vladimir K Date: Sun, 5 Apr 2020 19:43:41 -0700 Subject: [PATCH 1/5] Add libgpiod support --- .gitignore | 2 +- CMakeLists.txt | 12 +++++- cmake/modules/FindCompiler.cmake | 4 +- cmake/modules/Findgpiod.cmake | 23 +++++++++++ src/CMakeLists.txt | 2 + src/audio.h | 4 +- src/config.c | 37 +++++++++++++++++ src/direwolf.c | 3 ++ src/ptt.c | 70 ++++++++++++++++++++++++++++++-- 9 files changed, 149 insertions(+), 8 deletions(-) create mode 100644 cmake/modules/Findgpiod.cmake diff --git a/.gitignore b/.gitignore index 659c845b..b917a7ab 100644 --- a/.gitignore +++ b/.gitignore @@ -109,5 +109,5 @@ $RECYCLE.BIN/ *.dSYM # cmake -build/ +build*/ tmp/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a1cb8e2..930f2718 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,8 +143,8 @@ elseif(APPLE) message(STATUS "RPATH support: ${CMAKE_MACOSX_RPATH}") elseif (WIN32) - if(NOT VS2015 AND NOT VS2017) - message(FATAL_ERROR "You must use Microsoft Visual Studio 2015 or 2017 as compiler") + if(NOT VS2015 AND NOT VS2017 AND NOT VS2019) + message(FATAL_ERROR "You must use Microsoft Visual Studio 2015 | 2017 | 2019 as compiler") endif() # compile with full multicore @@ -251,6 +251,14 @@ else() set(HAMLIB_LIBRARIES "") endif() +find_package(gpiod) +if(GPIOD_FOUND) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_GPIOD") +else() + set(GPIOD_INCLUDE_DIRS "") + set(GPIOD_LIBRARIES "") +endif() + if(LINUX) find_package(ALSA REQUIRED) if(ALSA_FOUND) diff --git a/cmake/modules/FindCompiler.cmake b/cmake/modules/FindCompiler.cmake index f339a73e..91e1b89c 100644 --- a/cmake/modules/FindCompiler.cmake +++ b/cmake/modules/FindCompiler.cmake @@ -5,7 +5,9 @@ elseif(NOT DEFINED C_GCC AND CMAKE_CXX_COMPILER_ID MATCHES "GNU") set(C_GCC 1) elseif(NOT DEFINED C_MSVC AND CMAKE_CXX_COMPILER_ID MATCHES "MSVC") set(C_MSVC 1) - if(MSVC_VERSION GREATER 1910 AND MSVC_VERSION LESS 1919) + if(MSVC_VERSION GREATER 1919 AND MSVC_VERSION LESS 1926) + set(VS2019 ON) + elseif(MSVC_VERSION GREATER 1910 AND MSVC_VERSION LESS 1919) set(VS2017 ON) elseif(MSVC_VERSION GREATER 1899 AND MSVC_VERSION LESS 1910) set(VS2015 ON) diff --git a/cmake/modules/Findgpiod.cmake b/cmake/modules/Findgpiod.cmake new file mode 100644 index 00000000..bf5be305 --- /dev/null +++ b/cmake/modules/Findgpiod.cmake @@ -0,0 +1,23 @@ +# - Try to find libgpiod +# Once done this will define +# GPIOD_FOUND - System has libgpiod +# GPIOD_INCLUDE_DIRS - The libgpiod include directories +# GPIOD_LIBRARIES - The libraries needed to use libgpiod +# GPIOD_DEFINITIONS - Compiler switches required for using libgpiod + +find_package(PkgConfig) +pkg_check_modules(PC_GPIOD QUIET gpiod) + +find_path(GPIOD_INCLUDE_DIR gpiod.h) +find_library(GPIOD_LIBRARY NAMES gpiod) + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set GPIOD_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(gpiod DEFAULT_MSG + GPIOD_LIBRARY GPIOD_INCLUDE_DIR) + +mark_as_advanced(GPIOD_INCLUDE_DIR GPIOD_LIBRARY) + +set(GPIOD_LIBRARIES ${GPIOD_LIBRARY}) +set(GPIOD_INCLUDE_DIRS ${GPIOD_INCLUDE_DIR}) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 46d3ac7a..4f8e647f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,6 +8,7 @@ include_directories( ${UDEV_INCLUDE_DIRS} ${PORTAUDIO_INCLUDE_DIRS} ${CUSTOM_GEOTRANZ_DIR} + ${GPIOD_INCLUDE_DIRS} ) if(WIN32 OR CYGWIN) @@ -127,6 +128,7 @@ target_link_libraries(direwolf ${ALSA_LIBRARIES} ${UDEV_LIBRARIES} ${PORTAUDIO_LIBRARIES} + ${GPIOD_LIBRARIES} ) if(WIN32 OR CYGWIN) diff --git a/src/audio.h b/src/audio.h index 53768f20..654d16fc 100644 --- a/src/audio.h +++ b/src/audio.h @@ -28,7 +28,8 @@ enum ptt_method_e { PTT_METHOD_NONE, /* VOX or no transmit. */ PTT_METHOD_SERIAL, /* Serial port RTS or DTR. */ - PTT_METHOD_GPIO, /* General purpose I/O, Linux only. */ + PTT_METHOD_GPIO, /* General purpose I/O using sysfs, deprecated after 2020, Linux only. */ + PTT_METHOD_GPIOD, /* General purpose I/O, using libgpiod, Linux only. */ PTT_METHOD_LPT, /* Parallel printer port, Linux only. */ PTT_METHOD_HAMLIB, /* HAMLib, Linux only. */ PTT_METHOD_CM108 }; /* GPIO pin of CM108/CM119/etc. Linux only. */ @@ -266,6 +267,7 @@ struct audio_s { /* the case for CubieBoard where it was longer. */ /* This is filled in by ptt_init so we don't have to */ /* recalculate it each time we access it. */ + /* Also GPIO chip name for GPIOD method. Looks like 'gpiochip4' */ /* This could probably be collapsed into ptt_device instead of being separate. */ diff --git a/src/config.c b/src/config.c index 8f9cb9f9..e40a6521 100644 --- a/src/config.c +++ b/src/config.c @@ -1743,6 +1743,43 @@ void config_init (char *fname, struct audio_s *p_audio_config, } p_audio_config->achan[channel].octrl[ot].ptt_method = PTT_METHOD_GPIO; #endif + } + else if (strcasecmp(t, "GPIOD") == 0) { +#if __WIN32__ + text_color_set(DW_COLOR_ERROR); + dw_printf ("Config file line %d: %s with GPIOD is only available on Linux.\n", line, otname); +#else +#if defined(USE_GPIOD) + t = split(NULL,0); + if (t == NULL) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("Config file line %d: Missing GPIO chip for %s.\n", line, otname); + continue; + } + strlcpy(p_audio_config->achan[channel].octrl[ot].out_gpio_name, t, + sizeof(p_audio_config->achan[channel].octrl[ot].out_gpio_name)); + + t = split(NULL,0); + if (t == NULL) { + text_color_set(DW_COLOR_ERROR); + dw_printf("Config file line %d: Missing GPIO number for %s.\n", line, otname); + continue; + } + + if (*t == '-') { + p_audio_config->achan[channel].octrl[ot].out_gpio_num = atoi(t+1); + p_audio_config->achan[channel].octrl[ot].ptt_invert = 1; + } + else { + p_audio_config->achan[channel].octrl[ot].out_gpio_num = atoi(t); + p_audio_config->achan[channel].octrl[ot].ptt_invert = 0; + } + p_audio_config->achan[channel].octrl[ot].ptt_method = PTT_METHOD_GPIOD; +#else + text_color_set(DW_COLOR_ERROR); + dw_printf ("GPIOD is not supported.\n"); +#endif /* USE_GPIOD*/ +#endif /* __WIN32__ */ } else if (strcasecmp(t, "LPT") == 0) { diff --git a/src/direwolf.c b/src/direwolf.c index 8d6e8a7c..0e41f4fc 100644 --- a/src/direwolf.c +++ b/src/direwolf.c @@ -302,6 +302,9 @@ int main (int argc, char *argv[]) #endif #if defined(USE_CM108) dw_printf (" cm108-ptt"); +#endif +#if defined(USE_GPIOD) + dw_printf (" libgpiod"); #endif dw_printf ("\n"); #endif diff --git a/src/ptt.c b/src/ptt.c index cf49bbab..05eeeda3 100644 --- a/src/ptt.c +++ b/src/ptt.c @@ -166,6 +166,10 @@ #include "cm108.h" #endif +#ifdef USE_GPIOD +#include +#endif + /* So we can have more common code for fd. */ typedef int HANDLE; #define INVALID_HANDLE_VALUE (-1) @@ -623,6 +627,31 @@ void export_gpio(int ch, int ot, int invert, int direction) get_access_to_gpio (gpio_value_path); } +#if defined(USE_GPIOD) +int gpiod_probe(const char *chip_name, int line_number) +{ + struct gpiod_chip *chip; + chip = gpiod_chip_open_by_name(chip_name); + if (chip == NULL) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("Can't open GPIOD chip %s.\n", chip_name); + return -1; + } + + struct gpiod_line *line; + line = gpiod_chip_get_line(chip, line_number); + if (line == NULL) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("Can't get GPIOD line %d.\n", line_number); + return -1; + } + if (ptt_debug_level >= 2) { + text_color_set(DW_COLOR_DEBUG); + dw_printf("GPIOD probe OK. Chip: %s line: %d\n", chip_name, line_number); + } + return 0; +} +#endif /* USE_GPIOD */ #endif /* not __WIN32__ */ @@ -639,7 +668,8 @@ void export_gpio(int ch, int ot, int invert, int direction) * ptt_method Method for PTT signal. * PTT_METHOD_NONE - not configured. Could be using VOX. * PTT_METHOD_SERIAL - serial (com) port. - * PTT_METHOD_GPIO - general purpose I/O. + * PTT_METHOD_GPIO - general purpose I/O (sysfs). + * PTT_METHOD_GPIOD - general purpose I/O (libgpiod). * PTT_METHOD_LPT - Parallel printer port. * PTT_METHOD_HAMLIB - HAMLib rig control. * PTT_METHOD_CM108 - GPIO pins of CM108 etc. USB Audio. @@ -718,12 +748,13 @@ void ptt_init (struct audio_s *audio_config_p) if (ptt_debug_level >= 2) { text_color_set(DW_COLOR_DEBUG); - dw_printf ("ch=%d, %s method=%d, device=%s, line=%d, gpio=%d, lpt_bit=%d, invert=%d\n", + dw_printf ("ch=%d, %s method=%d, device=%s, line=%d, name=%s, gpio=%d, lpt_bit=%d, invert=%d\n", ch, otnames[ot], audio_config_p->achan[ch].octrl[ot].ptt_method, audio_config_p->achan[ch].octrl[ot].ptt_device, audio_config_p->achan[ch].octrl[ot].ptt_line, + audio_config_p->achan[ch].octrl[ot].out_gpio_name, audio_config_p->achan[ch].octrl[ot].out_gpio_num, audio_config_p->achan[ch].octrl[ot].ptt_lpt_bit, audio_config_p->achan[ch].octrl[ot].ptt_invert); @@ -869,7 +900,28 @@ void ptt_init (struct audio_s *audio_config_p) if (using_gpio) { get_access_to_gpio ("/sys/class/gpio/export"); } - +#if defined(USE_GPIOD) + // GPIOD + for (ch = 0; ch < MAX_CHANS; ch++) { + if (save_audio_config_p->achan[ch].medium == MEDIUM_RADIO) { + for (int ot = 0; ot < NUM_OCTYPES; ot++) { + if (audio_config_p->achan[ch].octrl[ot].ptt_method == PTT_METHOD_GPIOD) { + const char *chip_name = audio_config_p->achan[ch].octrl[ot].out_gpio_name; + int line_number = audio_config_p->achan[ch].octrl[ot].out_gpio_num; + int rc = gpiod_probe(chip_name, line_number); + if (rc < 0) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("Disable PTT for channel %d\n", ch); + audio_config_p->achan[ch].octrl[ot].ptt_method = PTT_METHOD_NONE; + } else { + // Set initial state off ptt_set will invert output signal if appropriate. + ptt_set (ot, ch, 0); + } + } + } + } + } +#endif /* USE_GPIOD */ /* * We should now be able to create the device nodes for * the pins we want to use. @@ -1226,6 +1278,18 @@ void ptt_set (int ot, int chan, int ptt_signal) close (fd); } + +#if defined(USE_GPIOD) + if (save_audio_config_p->achan[chan].octrl[ot].ptt_method == PTT_METHOD_GPIOD) { + const char *chip = save_audio_config_p->achan[chan].octrl[ot].out_gpio_name; + int line = save_audio_config_p->achan[chan].octrl[ot].out_gpio_num; + int rc = gpiod_ctxless_set_value(chip, line, ptt, false, "direwolf", NULL, NULL); + if (ptt_debug_level >= 1) { + text_color_set(DW_COLOR_DEBUG); + dw_printf("PTT_METHOD_GPIOD chip: %s line: %d ptt: %d rc: %d\n", chip, line, ptt, rc); + } + } +#endif /* USE_GPIOD */ #endif /* From 6192661f3df331c7abffe921b62db80994e0930e Mon Sep 17 00:00:00 2001 From: wb2osz Date: Sat, 25 Nov 2023 15:32:04 +0000 Subject: [PATCH 2/5] Compile error. --- src/audio.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/audio.h b/src/audio.h index cb5ca94e..ae1035d9 100644 --- a/src/audio.h +++ b/src/audio.h @@ -74,16 +74,23 @@ struct audio_s { /* Properties of the sound device. */ - int defined; /* Was device defined? */ - /* First one defaults to yes. */ + int defined; /* Was device defined? 0=no. >0 for yes. */ + /* First channel defaults to 2 for yes with default config. */ + /* 1 means it was defined by user. */ + + int copy_from; /* >=0 means copy contents from another audio device. */ + /* In this case we don't have device names, below. */ + /* Num channels, samples/sec, and bit/sample are copied from */ + /* original device and can't be changed. */ + /* -1 for normal case. */ char adevice_in[80]; /* Name of the audio input device (or file?). */ - /* TODO: Can be "-" to read from stdin. */ + /* Can be udp:nnn for UDP or "-" to read from stdin. */ char adevice_out[80]; /* Name of the audio output device (or file?). */ int num_channels; /* Should be 1 for mono or 2 for stereo. */ - int samples_per_sec; /* Audio sampling rate. Typically 11025, 22050, or 44100. */ + int samples_per_sec; /* Audio sampling rate. Typically 11025, 22050, 44100, or 48000. */ int bits_per_sample; /* 8 (unsigned char) or 16 (signed short). */ } adev[MAX_ADEVS]; From ad5dbaec73c1ac280f88177bc0aa635fc6e108e3 Mon Sep 17 00:00:00 2001 From: wb2osz Date: Sun, 26 Nov 2023 01:12:34 +0000 Subject: [PATCH 3/5] Refine ptt gpiod. --- src/config.c | 6 ++++-- src/ptt.c | 16 +++++++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/config.c b/src/config.c index faf4e8ff..747d0e60 100644 --- a/src/config.c +++ b/src/config.c @@ -1852,7 +1852,8 @@ void config_init (char *fname, struct audio_s *p_audio_config, t = split(NULL,0); if (t == NULL) { text_color_set(DW_COLOR_ERROR); - dw_printf ("Config file line %d: Missing GPIO chip for %s.\n", line, otname); + dw_printf ("Config file line %d: Missing GPIO chip name for %s.\n", line, otname); + dw_printf ("Use the \"gpioinfo\" command to get a list of gpio chip names and corresponding I/O lines.\n"); continue; } strlcpy(p_audio_config->achan[channel].octrl[ot].out_gpio_name, t, @@ -1876,7 +1877,8 @@ void config_init (char *fname, struct audio_s *p_audio_config, p_audio_config->achan[channel].octrl[ot].ptt_method = PTT_METHOD_GPIOD; #else text_color_set(DW_COLOR_ERROR); - dw_printf ("GPIOD is not supported.\n"); + dw_printf ("Application was not built with optional support for GPIOD.\n"); + dw_printf ("Install packages gpiod and libgpiod-dev, remove 'build' subdirectory, then rebuild.\n"); #endif /* USE_GPIOD*/ #endif /* __WIN32__ */ } diff --git a/src/ptt.c b/src/ptt.c index 6177d6d7..f6020394 100644 --- a/src/ptt.c +++ b/src/ptt.c @@ -472,6 +472,20 @@ void export_gpio(int ch, int ot, int invert, int direction) text_color_set(DW_COLOR_ERROR); dw_printf ("Error writing \"%s\" to %s, errno=%d\n", stemp, gpio_export_path, e); dw_printf ("%s\n", strerror(e)); + + if (e == 22) { + // It appears that error 22 occurs when sysfs gpio is not available. + // (See https://github.com/wb2osz/direwolf/issues/503) + // + // The solution might be to use the new gpiod approach. + + dw_printf ("It looks like gpio with sysfs is not supported on this operating system.\n"); + dw_printf ("Rather than the following form, in the configuration file,\n); + dw_printf (" PTT GPIO %s\n", stemp); + dw_printf ("try using gpiod form instead. e.g.\n"); + dw_printf (" PTT GPIOD gpiochip0 %s\n", stemp); + dw_printf ("You can get a list of gpio chip names and corresponding I/O lines with \"gpioinfo\" command.\n"); + } exit (1); } } @@ -914,7 +928,7 @@ void ptt_init (struct audio_s *audio_config_p) #if defined(USE_GPIOD) // GPIOD for (ch = 0; ch < MAX_CHANS; ch++) { - if (save_audio_config_p->achan[ch].medium == MEDIUM_RADIO) { + if (save_audio_config_p->chan_medium[ch] == MEDIUM_RADIO) { for (int ot = 0; ot < NUM_OCTYPES; ot++) { if (audio_config_p->achan[ch].octrl[ot].ptt_method == PTT_METHOD_GPIOD) { const char *chip_name = audio_config_p->achan[ch].octrl[ot].out_gpio_name; From 5d35780498e6c14c56e1cdf998409fff7b5ba380 Mon Sep 17 00:00:00 2001 From: wb2osz Date: Sun, 26 Nov 2023 01:29:13 +0000 Subject: [PATCH 4/5] missing quote --- src/ptt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ptt.c b/src/ptt.c index f6020394..a75cb8de 100644 --- a/src/ptt.c +++ b/src/ptt.c @@ -480,7 +480,7 @@ void export_gpio(int ch, int ot, int invert, int direction) // The solution might be to use the new gpiod approach. dw_printf ("It looks like gpio with sysfs is not supported on this operating system.\n"); - dw_printf ("Rather than the following form, in the configuration file,\n); + dw_printf ("Rather than the following form, in the configuration file,\n"); dw_printf (" PTT GPIO %s\n", stemp); dw_printf ("try using gpiod form instead. e.g.\n"); dw_printf (" PTT GPIOD gpiochip0 %s\n", stemp); From 336861813a3a9457dbfc52dd754ff3f95b92147f Mon Sep 17 00:00:00 2001 From: Brent Petit Date: Sun, 29 Oct 2023 21:05:29 -0500 Subject: [PATCH 5/5] Simplify queueing and locking --- src/dlq.c | 130 ++++++++++++++++++++++++++---------------------------- 1 file changed, 63 insertions(+), 67 deletions(-) diff --git a/src/dlq.c b/src/dlq.c index f56b8649..aa25b84f 100644 --- a/src/dlq.c +++ b/src/dlq.c @@ -60,6 +60,8 @@ /* The queue is a linked list of these. */ static struct dlq_item_s *queue_head = NULL; /* Head of linked list for queue. */ +static struct dlq_item_s *queue_tail = NULL; /* Tail of linked list for queue. */ +int queue_length = 0; /* Count of items in queue */ #if __WIN32__ @@ -75,8 +77,6 @@ static pthread_mutex_t dlq_mutex; /* Critical section for updating queues. */ static pthread_cond_t wake_up_cond; /* Notify received packet processing thread when queue not empty. */ -static pthread_mutex_t wake_up_mutex; /* Required by cond_wait. */ - static volatile int recv_thread_is_waiting = 0; #endif @@ -117,7 +117,8 @@ void dlq_init (void) dw_printf ("dlq_init ( )\n"); #endif - queue_head = NULL; + queue_head = queue_tail = NULL; + queue_length = 0; #if DEBUG @@ -129,13 +130,6 @@ void dlq_init (void) InitializeCriticalSection (&dlq_cs); #else int err; - err = pthread_mutex_init (&wake_up_mutex, NULL); - if (err != 0) { - text_color_set(DW_COLOR_ERROR); - dw_printf ("dlq_init: pthread_mutex_init err=%d", err); - perror (""); - exit (EXIT_FAILURE); - } err = pthread_mutex_init (&dlq_mutex, NULL); if (err != 0) { text_color_set(DW_COLOR_ERROR); @@ -314,9 +308,6 @@ void dlq_rec_frame (int chan, int subchan, int slice, packet_t pp, alevel_t alev static void append_to_queue (struct dlq_item_s *pnew) { - struct dlq_item_s *plast; - int queue_length = 0; - if ( ! was_init) { dlq_init (); } @@ -341,30 +332,19 @@ static void append_to_queue (struct dlq_item_s *pnew) #endif if (queue_head == NULL) { - queue_head = pnew; + assert (queue_tail == NULL); + queue_head = queue_tail = pnew; queue_length = 1; + } else { + assert (queue_tail != NULL); + queue_tail->nextp = pnew; + queue_tail = pnew; + queue_length++; + assert (queue_length > 1); } - else { - queue_length = 2; /* head + new one */ - plast = queue_head; - while (plast->nextp != NULL) { - plast = plast->nextp; - queue_length++; - } - plast->nextp = pnew; - } - #if __WIN32__ LeaveCriticalSection (&dlq_cs); -#else - err = pthread_mutex_unlock (&dlq_mutex); - if (err != 0) { - text_color_set(DW_COLOR_ERROR); - dw_printf ("dlq append_to_queue: pthread_mutex_unlock err=%d", err); - perror (""); - exit (1); - } #endif #if DEBUG1 text_color_set(DW_COLOR_DEBUG); @@ -416,7 +396,7 @@ static void append_to_queue (struct dlq_item_s *pnew) * and blocking on a write. */ - if (queue_length > 10) { + if (queue_length > 15) { text_color_set(DW_COLOR_ERROR); dw_printf ("Received frame queue is out of control. Length=%d.\n", queue_length); dw_printf ("Reader thread is probably frozen.\n"); @@ -431,14 +411,6 @@ static void append_to_queue (struct dlq_item_s *pnew) #else if (recv_thread_is_waiting) { - err = pthread_mutex_lock (&wake_up_mutex); - if (err != 0) { - text_color_set(DW_COLOR_ERROR); - dw_printf ("dlq append_to_queue: pthread_mutex_lock wu err=%d", err); - perror (""); - exit (1); - } - err = pthread_cond_signal (&wake_up_cond); if (err != 0) { text_color_set(DW_COLOR_ERROR); @@ -446,14 +418,14 @@ static void append_to_queue (struct dlq_item_s *pnew) perror (""); exit (1); } + } - err = pthread_mutex_unlock (&wake_up_mutex); - if (err != 0) { - text_color_set(DW_COLOR_ERROR); - dw_printf ("dlq append_to_queue: pthread_mutex_unlock wu err=%d", err); - perror (""); - exit (1); - } + err = pthread_mutex_unlock (&dlq_mutex); + if (err != 0) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("dlq append_to_queue: pthread_mutex_unlock wu err=%d", err); + perror (""); + exit (1); } #endif @@ -1011,9 +983,29 @@ int dlq_wait_while_empty (double timeout) dlq_init (); } +#if DEBUG1 + text_color_set(DW_COLOR_DEBUG); + dw_printf ("dlq dlq_wait_while_empty: enter critical section\n"); +#endif +#if __WIN32__ + EnterCriticalSection (&dlq_cs); +#else + int err; + err = pthread_mutex_lock (&dlq_mutex); + if (err != 0) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("dlq append_to_queue: pthread_mutex_lock err=%d", err); + perror (""); + exit (1); + } +#endif if (queue_head == NULL) { +#if __WIN32__ + LeaveCriticalSection (&dlq_cs); +#endif + #if DEBUG text_color_set(DW_COLOR_DEBUG); dw_printf ("dlq_wait_while_empty (): prepare to SLEEP...\n"); @@ -1037,18 +1029,15 @@ int dlq_wait_while_empty (double timeout) else { WaitForSingleObject (wake_up_event, INFINITE); } + } else { +#if __WIN32__ + LeaveCriticalSection (&dlq_cs); +#endif + } #else int err; - err = pthread_mutex_lock (&wake_up_mutex); - if (err != 0) { - text_color_set(DW_COLOR_ERROR); - dw_printf ("dlq_wait_while_empty: pthread_mutex_lock wu err=%d", err); - perror (""); - exit (1); - } - recv_thread_is_waiting = 1; if (timeout != 0.0) { struct timespec abstime; @@ -1056,26 +1045,25 @@ int dlq_wait_while_empty (double timeout) abstime.tv_sec = (time_t)(long)timeout; abstime.tv_nsec = (long)((timeout - (long)abstime.tv_sec) * 1000000000.0); - err = pthread_cond_timedwait (&wake_up_cond, &wake_up_mutex, &abstime); + err = pthread_cond_timedwait (&wake_up_cond, &dlq_mutex, &abstime); if (err == ETIMEDOUT) { timed_out_result = 1; } } else { - err = pthread_cond_wait (&wake_up_cond, &wake_up_mutex); + err = pthread_cond_wait (&wake_up_cond, &dlq_mutex); } recv_thread_is_waiting = 0; - - err = pthread_mutex_unlock (&wake_up_mutex); - if (err != 0) { - text_color_set(DW_COLOR_ERROR); - dw_printf ("dlq_wait_while_empty: pthread_mutex_unlock wu err=%d", err); - perror (""); - exit (1); - } -#endif } + err = pthread_mutex_unlock (&dlq_mutex); + if (err != 0) { + text_color_set(DW_COLOR_ERROR); + dw_printf ("dlq_wait_while_empty: pthread_mutex_unlock wu err=%d", err); + perror (""); + exit (1); + } +#endif #if DEBUG text_color_set(DW_COLOR_DEBUG); @@ -1133,6 +1121,14 @@ struct dlq_item_s *dlq_remove (void) if (queue_head != NULL) { result = queue_head; queue_head = queue_head->nextp; + queue_length--; + if (queue_head == NULL) { + assert (queue_length == 0); + queue_tail = NULL; + } + if (queue_length == 1) { + assert (queue_head == queue_tail); + } } #if __WIN32__