Changeset: e1ab5c093c74 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/e1ab5c093c74 Branch: strimps_update Log Message:
Merge with default diffs (truncated from 3259 to 300 lines): diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -763,3 +763,4 @@ cab90a348501b045e19cee5cebcc44f3800bd0a8 5872f047d97c98d3a848514438b8f97fa446855d Jan2022_11 025239a5a6f122042798c0f1132a2c6298514e06 Jan2022_13 025239a5a6f122042798c0f1132a2c6298514e06 Jan2022_SP2_release +2e54857a91306cc6304825c5596f65d00595db6b Jul2021_23 diff --git a/MonetDB.spec b/MonetDB.spec --- a/MonetDB.spec +++ b/MonetDB.spec @@ -365,6 +365,7 @@ developer. %{_bindir}/smack00 %{_bindir}/smack01 %{_bindir}/streamcat +%{_bindir}/testcondvar %{_bindir}/testgetinfo %{_bindir}/testStmtAttr %{_bindir}/malsample.pl diff --git a/buildtools/conf/Maddlog b/buildtools/conf/Maddlog --- a/buildtools/conf/Maddlog +++ b/buildtools/conf/Maddlog @@ -189,6 +189,9 @@ fi file=ChangeLog.$RANDOM +# make sure we get the correct day and month names +export LC_ALL=en_US.utf-8 + case "$CL" in */*) cd "${CL%/*}" diff --git a/clients/Tests/All b/clients/Tests/All --- a/clients/Tests/All +++ b/clients/Tests/All @@ -3,3 +3,4 @@ HAVE_HGE&HAVE_FITS&HAVE_GEOM&HAVE_LIBR&H !HAVE_HGE&HAVE_FITS&HAVE_GEOM&HAVE_LIBR&HAVE_LIBPY3&HAVE_NETCDF&HAVE_SHP&NOT_WIN32?MAL-signatures NOT_WIN32&MERCURIAL?melcheck mclient-uri +testcondvar diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out --- a/clients/Tests/exports.stable.out +++ b/clients/Tests/exports.stable.out @@ -536,23 +536,23 @@ ssize_t lngFromStr(const char *src, size ssize_t lngToStr(str *dst, size_t *len, const lng *src, bool external); const lng lng_nil; struct tm *localtime_r(const time_t *restrict, struct tm *restrict); +gdk_return log_activate(logger *lg); gdk_return log_bat(logger *lg, BAT *b, log_id id, lng offset, lng cnt); gdk_return log_bat_clear(logger *lg, log_id id); gdk_return log_bat_persists(logger *lg, BAT *b, log_id id); gdk_return log_bat_transient(logger *lg, log_id id); +lng log_changes(logger *lg); gdk_return log_constant(logger *lg, int type, ptr val, log_id id, lng offset, lng cnt); +logger *log_create(int debug, const char *fn, const char *logdir, int version, preversionfix_fptr prefuncp, postversionfix_fptr postfuncp, void *funcdata); gdk_return log_delta(logger *lg, BAT *uid, BAT *uval, log_id id); -gdk_return log_sequence(logger *lg, int seq, lng id); +void log_destroy(logger *lg); +log_bid log_find_bat(logger *lg, log_id id); +gdk_return log_flush(logger *lg, ulng saved_id); +int log_sequence(logger *lg, int seq, lng *id); gdk_return log_tend(logger *lg); gdk_return log_tflush(logger *lg, ulng log_file_id, ulng commit_ts); +gdk_return log_tsequence(logger *lg, int seq, lng id); gdk_return log_tstart(logger *lg, bool flushnow, ulng *log_file_id); -gdk_return logger_activate(logger *lg); -lng logger_changes(logger *lg); -logger *logger_create(int debug, const char *fn, const char *logdir, int version, preversionfix_fptr prefuncp, postversionfix_fptr postfuncp, void *funcdata); -void logger_destroy(logger *lg); -log_bid logger_find_bat(logger *lg, log_id id); -gdk_return logger_flush(logger *lg, ulng saved_id); -int logger_sequence(logger *lg, int seq, lng *id); log_level_t lvl_per_component[]; void *mdlopen(const char *library, int mode); const char *mercurial_revision(void) __attribute__((__const__)); diff --git a/clients/Tests/testcondvar.py b/clients/Tests/testcondvar.py new file mode 100644 --- /dev/null +++ b/clients/Tests/testcondvar.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 + +import subprocess +import sys + +try: + subprocess.check_output("testcondvar", stderr=subprocess.STDOUT) +except subprocess.CalledProcessError as e: + output = str(e.stdout, 'utf-8') + if not output.endswith('\n'): + output += '\n' + print(f"Test program failed with the following output:\n------", file=sys.stderr) + print(f"{output}-----", file=sys.stderr) + sys.exit('TEST FAILED') diff --git a/clients/examples/C/CMakeLists.txt b/clients/examples/C/CMakeLists.txt --- a/clients/examples/C/CMakeLists.txt +++ b/clients/examples/C/CMakeLists.txt @@ -45,6 +45,16 @@ if(TESTING) monetdb_config_header stream) + add_executable(testcondvar + testcondvar.c) + + target_link_libraries(testcondvar + PRIVATE + monetdb_config_header + bat + Threads::Threads + ) + add_executable(bincopydata bincopydata.c bincopydata.h @@ -75,6 +85,7 @@ if(TESTING) smack00 smack01 streamcat + testcondvar bincopydata RUNTIME DESTINATION @@ -89,6 +100,7 @@ if(TESTING) $<TARGET_PDB_FILE:smack00> $<TARGET_PDB_FILE:smack01> $<TARGET_PDB_FILE:streamcat> + $<TARGET_PDB_FILE:testcondvar> $<TARGET_PDB_FILE:bincopydata> $<TARGET_PDB_FILE:bincopyloops> DESTINATION ${CMAKE_INSTALL_BINDIR} diff --git a/clients/examples/C/testcondvar.c b/clients/examples/C/testcondvar.c new file mode 100644 --- /dev/null +++ b/clients/examples/C/testcondvar.c @@ -0,0 +1,183 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V. + */ + +#include "monetdb_config.h" +#include "gdk.h" +#include "gdk_system.h" + +#include <assert.h> + +#define NN (3) + +volatile int timeout = 100; // set this to 0 during interactive debugging + +/* global state protected by a lock: */ + +MT_Lock lock = MT_LOCK_INITIALIZER(lock); +MT_Cond condvar = MT_COND_INITIALIZER(the_condvar); +struct state { + MT_Id id; + int ticks; + int permits; + bool terminate; + bool terminated; +} states[NN] = { {0} }; + + +static void +let_run(void) +{ + MT_lock_unset(&lock); + + MT_sleep_ms(100); + + int attempts = 0; + while (!MT_lock_try(&lock)) { + if (timeout > 0 && ++attempts > timeout) { + fprintf(stderr, "Can't get hold of the lock after %d attempts\n", attempts); + abort(); + } + MT_sleep_ms(10); + } + + fprintf(stderr, "\n"); +} + + +static void +worker(void *arg) +{ + struct state *st = arg; + int id = (int)(st - &states[0]); + fprintf(stderr, "worker %d starting\n", id); + + MT_lock_set(&lock); + while (1) { + if (st->terminate) { + fprintf(stderr, "worker %d terminating\n", id); + break; + } + if (st->permits > 0) { + fprintf(stderr, "worker %d ticking\n", id); + st->ticks++; + st->permits--; + } + fprintf(stderr, "worker %d waiting\n", id); + MT_cond_wait(&condvar, &lock); + fprintf(stderr, "worker %d woke up\n", id); + } + st->terminated = true; + MT_lock_unset(&lock); +} + + +static void clear(void) +{ + for (int i = 0; i < NN; i++) { + struct state *st = &states[i]; + st->permits = 0; + st->ticks = 0; + } +} + + +static void +check_impl(int line, int expected_sum_ticks, int expected_max_ticks, int expected_sum_permits) +{ + int sum_ticks = 0; + int max_ticks = -1; + int sum_permits = 0; + + for (int i = 0; i < NN; i++) { + sum_permits += states[i].permits; + int ticks = states[i].ticks; + sum_ticks += ticks; + if (ticks > max_ticks) + max_ticks = ticks; + } + + bool good = true; + good &= (sum_ticks == expected_sum_ticks); + good &= (max_ticks == expected_max_ticks); + good &= (sum_permits == expected_sum_permits); + if (good) + return; + + fprintf(stderr, "\nOn line %d:\n", line); + fprintf(stderr, "Expect sum ticks to be %d, is %d\n", expected_sum_ticks, sum_ticks); + fprintf(stderr, "Expect max ticks to be %d, is %d\n", expected_max_ticks, max_ticks); + fprintf(stderr, "Expect sum permits to be %d, is %d\n", expected_sum_permits, sum_permits); + for (int i = 0; i < NN; i++) { + fprintf(stderr, "worker %d: ticks=%d permits=%d\n", i, states[i].ticks, states[i].permits); + } + abort(); +} + +#define check(expected_sum, expected_max, expected_permits) check_impl(__LINE__, expected_sum, expected_max, expected_permits) + +int +main(void) +{ + MT_thread_init(); + + MT_lock_set(&lock); + check(0, 0, 0); + + for (int i = 0; i < NN; i++) { + struct state *st = &states[i]; + char name[MT_NAME_LEN]; + snprintf(name, sizeof(name), "worker%d", i); + MT_create_thread(&st->id, worker, st, MT_THR_JOINABLE, name); + } + check(0, 0, 0); + + let_run(); + check(0, 0, 0); + + // give them all a permit and broadcast on the condvar. they should all run + for (int i = 0; i < NN; i++) + states[i].permits = 1; + let_run(); + // haven't notified them yet: + check(0, 0, 3); + MT_cond_broadcast(&condvar); + let_run(); + check(3, 1, 0); + + // when using signal, we need to trigger them three times + clear(); + for (int i = 0; i < NN; i++) + states[i].permits = 1; + let_run(); + check(0, 0, 3); + MT_cond_signal(&condvar); + let_run(); + check(1, 1, 2); + MT_cond_signal(&condvar); + let_run(); + check(2, 1, 1); + MT_cond_signal(&condvar); + let_run(); _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org