Skip to content
Browse files

[6model/c] gather returned data from multiple threads, Configure fixes

  • Loading branch information...
1 parent 2bed502 commit d7d1a1075d6d3efbdcaacaf7bb1aa715c0c1565c @mberends mberends committed
Showing with 251 additions and 124 deletions.
  1. +69 −69 c/Configure.bat
  2. +127 −15 c/t/01-toolchain/01c-threads.c
  3. +5 −12 c/t/02-components/02a-hashtable.c
  4. +45 −23 c/tools/build/Configure.c
  5. +5 −5 c/tools/build/Makefile.in
View
138 c/Configure.bat
@@ -1,69 +1,69 @@
-:: Configure.bat
-
-:: This script should work on a Microsoft Windows operating system with
-:: either Microsoft Visual C++ or GNU Compiler Collection gcc.
-
-:: TODO
-:: - Add a --help option and provide for more options in general
-
-@echo off
-:: Determine whether the C compiler is MSVC or GCC, by attempting to use
-:: them in that order.
-echo int main(int argc, char * argv[]) { return 0; } >tools\build\temp.c
-cl -nologo -Fotools\build\temp.obj -Fetools\build\temp.exe tools\build\temp.c >nul 2>nul
-if not errorlevel 1 goto :msvc
-gcc -otools\build\temp.exe tools\build\temp.c
-if not errorlevel 1 goto :gcc
-cc tools\build\temp.c
-if not errorlevel 1 goto :cc
-echo Sorry! Cannot compile with eith cl, gcc or cc. Please fix.
-if exist tools\build\temp.exe del tools\build\temp.exe
-if exist tools\build\temp.obj del tools\build\temp.obj
-if exist tools\build\temp.c del tools\build\temp.c
-goto :end_of_script
-:msvc
-echo Detected Microsoft Visual C/C++ (cl.exe)
-del tools\build\temp.obj tools\build\temp.exe tools\build\temp.c
-set COMPILER=MSVC
-goto :got_compiler
-:gcc
-echo Detected GNU Compiler Collection (gcc.exe)
-del tools\build\temp.exe tools\build\temp.c
-set COMPILER=GCC
-goto :got_compiler
-:cc
-
-:got_compiler
-echo Compiling tools\build\Configure.c to tools\build\Configure.exe
-
-:: !!! FUD WARNING !!!
-:: Microsoft thinks that C programmers should rewrite every call to,
-:: for example, strcpy, replacing it with their more "secure"
-:: replacement called strcpy_s, which takes additional parameters to
-:: avoid buffer overruns. Microsoft's C compilers emit many loud
-:: warnings containing weasel words such as "fopen ... may be unsafe".
-:: http://msdn.microsoft.com/en-us/library/8ef0s5kh%28v=VS.100%29.aspx
-:: Talk about a brazen lock-in attempt! Since other target platforms
-:: are not blessed with strcpy_s and so on, this project opts to
-:: continue using the "older, less secure functions" and disable the
-:: warnings with -D_CRT_SECURE_NO_WARNINGS
-set opts_msvc=-nologo -Wall -DCC=MSVC -D_CRT_SECURE_NO_WARNINGS
-set opts_gcc=-Wall -DCC=GCC
-if "%COMPILER%"=="MSVC" cl %opts_msvc% -Fotools\build\Configure.obj -Fetools\build\Configure.exe tools\build\Configure.c
-if "%COMPILER%"=="GCC" gcc %opts_gcc% -otools\build\Configure.exe tools\build\Configure.c
-if errorlevel 1 goto :end_of_script
-if exist tools\build\Configure.obj del tools\build\Configure.obj
-:: echo Run tools\build\Configure.exe to create Makefile
-tools\build\Configure.exe tools\build\Makefile.in Makefile
-
-:end_of_script
-
-:: Notes
-
-:: Configure.bat or Configure.cmd?
-:: There is almost no difference between the two file types (just something
-:: subtle about errorlevel), and in 6model/c they work the same. So on user
-:: friendliness grounds, .bat reassures the reader that the script will do
-:: only "simple" things.
-:: You could argue it the other way - we use cmd.exe, not command.com, so we
-:: should use the extension that command.com cannot handle. Dunno...
+:: Configure.bat
+
+:: This script should work on a Microsoft Windows operating system with
+:: either Microsoft Visual C++ or GNU Compiler Collection gcc.
+
+:: TODO
+:: - Add a --help option and provide for more options in general
+
+@echo off
+:: Determine whether the C compiler is MSVC or GCC, by attempting to use
+:: them in that order.
+echo int main(int argc, char * argv[]) { return 0; } >tools\build\temp.c
+cl -nologo -Fotools\build\temp.obj -Fetools\build\temp.exe tools\build\temp.c >nul 2>nul
+if not errorlevel 1 goto :msvc
+gcc -otools\build\temp.exe tools\build\temp.c
+if not errorlevel 1 goto :gcc
+cc tools\build\temp.c
+if not errorlevel 1 goto :cc
+echo Sorry! Cannot compile with eith cl, gcc or cc. Please fix.
+if exist tools\build\temp.exe del tools\build\temp.exe
+if exist tools\build\temp.obj del tools\build\temp.obj
+if exist tools\build\temp.c del tools\build\temp.c
+goto :end_of_script
+:msvc
+echo Detected Microsoft Visual C/C++ (cl.exe)
+del tools\build\temp.obj tools\build\temp.exe tools\build\temp.c
+set COMPILER=MSVC
+goto :got_compiler
+:gcc
+echo Detected GNU Compiler Collection (gcc.exe)
+del tools\build\temp.exe tools\build\temp.c
+set COMPILER=GCC
+goto :got_compiler
+:cc
+
+:got_compiler
+echo Compiling tools\build\Configure.c to tools\build\Configure.exe
+
+:: !!! FUD WARNING !!!
+:: Microsoft thinks that C programmers should rewrite every call to,
+:: for example, strcpy, replacing it with their more "secure"
+:: replacement called strcpy_s, which takes additional parameters to
+:: avoid buffer overruns. Microsoft's C compilers emit many loud
+:: warnings containing weasel words such as "fopen ... may be unsafe".
+:: http://msdn.microsoft.com/en-us/library/8ef0s5kh%28v=VS.100%29.aspx
+:: Talk about a brazen lock-in attempt! Since other target platforms
+:: are not blessed with strcpy_s and so on, this project opts to
+:: continue using the "older, less secure functions" and disable the
+:: warnings with -D_CRT_SECURE_NO_WARNINGS
+set opts_msvc=-nologo -Wall -DCC=MSVC -D_CRT_SECURE_NO_WARNINGS -wd4820 -wd4668 -wd4255
+set opts_gcc=-Wall -DCC=GCC
+if "%COMPILER%"=="MSVC" cl %opts_msvc% -Fotools\build\Configure.obj -Fetools\build\Configure.exe tools\build\Configure.c
+if "%COMPILER%"=="GCC" gcc %opts_gcc% -otools\build\Configure.exe tools\build\Configure.c
+if errorlevel 1 goto :end_of_script
+if exist tools\build\Configure.obj del tools\build\Configure.obj
+:: echo Run tools\build\Configure.exe to create Makefile
+tools\build\Configure.exe tools\build\Makefile.in Makefile
+
+:end_of_script
+
+:: Notes
+
+:: Configure.bat or Configure.cmd?
+:: There is almost no difference between the two file types (just something
+:: subtle about errorlevel), and in 6model/c they work the same. So on user
+:: friendliness grounds, .bat reassures the reader that the script will do
+:: only "simple" things.
+:: You could argue it the other way - we use cmd.exe, not command.com, so we
+:: should use the extension that command.com cannot handle. Dunno...
View
142 c/t/01-toolchain/01c-threads.c
@@ -1,20 +1,21 @@
/* 01c-threads.c */
-/* Check that threading in the operating system and libraries are ok */
+/* Check that threading in the operating system and libraries is ok */
-
-#include <stdio.h> /* perror printf */
-#include <stdlib.h> /* system */
-#include "../Test.h" /* is_ii plan */
+#include <assert.h> /* assert */
+#include <stdio.h> /* perror printf */
+#include <stdlib.h> /* system */
+#include <string.h> /* strlen */
+#include "../Test.h" /* diag is_ii ok plan */
#ifdef _WIN32
#include <windows.h>
#define sleep(seconds) Sleep(seconds*1000)
#else
- #include <pthread.h> /* pthread_create */
+ #include <pthread.h> /* pthread_create pthread_join */
#endif
-struct threadargs {
+struct test1_threadargs {
int testnumber;
int seconds;
char * description;
@@ -25,17 +26,24 @@ struct threadargs {
void *
test1_thread(void * args)
{
- struct threadargs * targs = (struct threadargs *) args;
- int testnumber = targs->testnumber;
- char * description = targs->description;
+ int testnumber;
+ char * description;
+ char message[80];
+ struct test1_threadargs * targs;
+
+ targs = (struct test1_threadargs *) args;
+ testnumber = targs->testnumber;
+ description = targs->description;
sleep(targs->seconds);
- printf("ok %d - from %s thread\n", testnumber, description);
+ sprintf(message, "from %s thread", description);
+ ok(1, message);
return NULL;
}
+
/* tests_1_4 */
void
-tests1_4()
+tests1_4sleeps()
{
int status;
#ifdef _WIN32
@@ -46,7 +54,7 @@ tests1_4()
pthread_attr_t thread_attr;
#endif
int threadnumber, threadstacksize;
- struct threadargs thread1arguments, thread2arguments;
+ struct test1_threadargs thread1arguments, thread2arguments;
/* Create the first thread */
thread1arguments.testnumber = 3;
@@ -90,13 +98,117 @@ tests1_4()
}
+/* charcount_args */
+/* Input and output parameters for the threaded charcount test */
+struct charcount_args {
+ char * textdata;
+ int textlength;
+ char sought;
+ int finds;
+};
+
+
+/* charcount */
+void *
+charcount(void * argptr)
+{
+ char * s, sought;
+ int len, count;
+ struct charcount_args * args;
+ args = (struct charcount_args *) argptr;
+ s = args->textdata;
+ len = args->textlength;
+ sought = args->sought;
+ count = 0;
+ while (len--) {
+ if (* s++ == sought) {
+ ++count;
+ }
+ }
+ args->finds = count;
+ return NULL;
+}
+
+
+/* tests5_6charcount */
+/* */
+void
+tests5_6charcount()
+{
+ char message[80], s01[] =
+"Mostly, we're just a bunch of ants all cooperating (sort of) to haul"
+"food toward the nest (on average). There are many groups of people"
+"working on various bits and pieces as they see fit, since this is"
+"primarily a volunteer effort.";
+ struct charcount_args args[4];
+ int i, sublength, threadstacksize, status, totalfinds;
+ #ifdef _WIN32
+ HANDLE threadhandle[4];
+ DWORD threadId[4];
+ #else
+ pthread_t thread_id[4];
+ pthread_attr_t thread_attr;
+ #endif
+
+ /* Prepare search arguments for four search threads each dealing */
+ /* with a substring */
+ sublength = strlen(s01) / 4;
+ for (i=0; i<4; ++i) {
+ args[i].textdata = s01 + i * sublength;
+ args[i].textlength = i < 3 ? sublength : (strlen(s01) - 3 * sublength);
+ args[i].sought = ' ';
+ args[i].finds = -1;
+ }
+
+ /* Start the four search threads */
+ threadstacksize = 16384; /* Minimum allowed by Posix threads */
+ for (i=0; i<4; ++i) {
+ #ifdef _WIN32
+ threadhandle[i] = CreateThread(NULL, threadstacksize,
+ (LPTHREAD_START_ROUTINE) charcount, &args[i], 0,
+ &threadId[i]);
+ status = (threadhandle[i] == NULL);
+ #else
+ status = pthread_attr_init(&thread_attr);
+ pthread_attr_setstacksize(&thread_attr, threadstacksize);
+ status = pthread_create(&thread_id[i], &thread_attr,
+ charcount, &args[i]);
+ #endif
+ assert( status == 0 );
+ }
+
+ /* Wait for the four threads to finish */
+ totalfinds = 0;
+ for (i=0; i<4; ++i) {
+ #ifdef _WIN32
+ status = WaitForSingleObject(threadhandle[i], INFINITE);
+ #else
+ status = pthread_join(thread_id[i], NULL);
+ #endif
+ totalfinds += args[i].finds;
+ assert( status == 0 );
+ }
+
+ /* Perform a single search in the main thread */
+ args[0].textdata = s01;
+ args[0].textlength = strlen(s01);
+ args[0].sought = ' ';
+ args[0].finds = -1;
+ charcount(&args[0]);
+ sprintf(message, "found %d occurrences of '%c' both single and "
+ "multi threaded", args[0].finds, args[0].sought);
+ ok(args[0].finds == totalfinds, message);
+}
+
+
/* main */
int
main(int arg, char * argv[])
{
diag("01c-threads");
- plan(4);
- tests1_4(); /* two simple child threads */
+ plan(5);
+ tests1_4sleeps(); /* two threads that sleep and print */
+ tests5_6charcount(); /* four threads returning integers */
return 0;
}
View
17 c/t/02-components/02a-hashtable.c
@@ -9,7 +9,6 @@
#include <stdio.h> /* printf */
#include <stdlib.h> /* malloc */
#include <string.h> /* memmove strlen */
-#include <sys/time.h> /* gettimeofday */
#include "../../src/hashtable.h"
#include "../Test.h" /* diag is plan */
@@ -90,29 +89,24 @@ random_string(int maxlength)
/* main */
int main(int argc, char *argv[])
{
- struct timeval time_now, time_write, time_read;
struct hashtable * hashtable;
struct hashtable_iterator iter;
struct hashtable_entry entry;
void * valuepointer;
- int valueint, seed, stringcount = 0, stringlength, key_bytes = 0,
+ int valueint, seed = 0, stringcount = 0, stringlength, key_bytes = 0,
value_bytes = 0, entrynumber, collisions = 0, delete_count;
- char * source, * destination;
+ char * source, * destination, * value;
diag("02a-hashtable");
plan(4);
- gettimeofday(&time_now, NULL);
- time_write.tv_sec = time_now.tv_sec + 5;
- time_write.tv_usec = time_now.tv_usec;
- seed = time_now.tv_sec ^ time_now.tv_usec;
hashtable = hashtable_new();
- srand(seed);
+ srand(seed); /* TODO: get a portable seed from for example current time */
while (stringcount<STRINGCOUNT) { /* nondeterministic because of collisions */
char * key = random_string(MAXKEYLENGTH);
/* create a value consisting of the key reversed followed by */
/* the original key, for example 'abc' -> 'cbaabc' */
stringlength = strlen(key);
- char * value = (char *) malloc(2 * stringlength + 1);
+ value = (char *) malloc(2 * stringlength + 1);
destination=value+stringlength;
* destination -- = '\0';
for (source=key; stringlength-->0; ) {
@@ -133,7 +127,6 @@ int main(int argc, char *argv[])
value_bytes += strlen(value);
++ stringcount;
}
- gettimeofday(&time_now, NULL);
}
is_ii( stringcount, STRINGCOUNT, "created a hash with 5000 entries");
srand(seed);
@@ -167,4 +160,4 @@ int main(int argc, char *argv[])
}
#endif
-/* end of 02a-hashtable.c */
+/* end of 02a-hashtable.c */
View
68 c/tools/build/Configure.c
@@ -58,12 +58,17 @@
#include <stdio.h> /* fclose fgets FILE fopen fprintf printf stderr */
#include <stdlib.h> /* exit free getenv malloc realloc */
#include <string.h> /* memmove memcpy strcpy strlen strstr */
-#if __APPLE__
+#ifdef __APPLE__
#include <sys/sysctl.h>
-#elif __linux__
- #include <unistd.h> /* sysconf */
-#elif _WIN32
- #include <windows.h> /* GetSystemInfo */
+#else
+ #ifdef __linux__
+ #include <unistd.h> /* sysconf */
+ #else
+ #ifdef _WIN32
+ #include <windows.h> /* GetSystemInfo */
+ /* note Microsoft C 2010 needs -wd4820 -wd4668 -wd4255 */
+ #endif
+ #endif
#endif
#define LINEBUFFERSIZE 128
@@ -72,7 +77,7 @@ enum { OS_VAR,
DETECTED_END /* This one must always be last */};
char * detected[DETECTED_END] = {""};
/* Subscript names for configuration strings. Almost like a hash ;) */
-enum { CC, EXE, LDL, MAKE_COMMAND, OSTYPE, OUTFILE, RM_RF,
+enum { CC, EXE, LDL, MAKE_COMMAND, OSTYPE, OUTFILE, RM_RF, THREADS,
CONFIG_END /* this one must always be last */ };
/* note the words OS_TYPE and OUT clash with MinGW */
char * config[CONFIG_END] = {"", "", "", "", "", "", ""};
@@ -86,50 +91,53 @@ void trans(char ** text, char * search, char * replace);
/* detection */
/* Find and show differences between compilers and operating systems */
void
-detection()
+detection(void)
{
+ int processors = 0;
+ #if defined( _WIN32 )
+ SYSTEM_INFO sysinfo; /* declare up here because MSC hates it lower */
+ #endif
printf("Configure detects the following:\n");
/* Operating system */
printf(" Operating system in C predefined macro: ");
- #if __APPLE__
+ #if defined( __APPLE__ )
printf("__APPLE__");
#endif
- #if __linux__
+ #if defined( __linux__ )
printf("__linux__");
#endif
- #if _WIN32
+ #if defined( _WIN32 )
printf("_WIN32");
#endif
- #if !(__APPLE__ | __linux__ | _WIN32)
+ #if !(defined(__APPLE__) || defined(__linux__) || defined(_WIN32))
printf("unknown\n (not __APPLE__ __linux__ or _WIN32)\n");
#endif
printf("\n");
/* C compiler */
printf(" C compiler in predefined macro: ");
- #if __GNUC__
+ #if defined( __GNUC__ )
printf("__GNUC__");
#endif
- #if _MSC_VER
+ #if defined( _MSC_VER )
printf("_MSC_VER");
#endif
- #if !(__GNUC__ | _MSC_VER)
- printf("unknown\n (not __GNUC__ or _MSC_VER)")
+ #if !(defined( __GNUC__ ) || defined( _MSC_VER ))
+ printf("unknown\n (not __GNUC__ or _MSC_VER)");
#endif
printf("\n");
/* Number of processors */
- int processors = 0;
/* from http://stackoverflow.com/questions/150355/programmatically-find-the-number-of-cores-on-a-machine */
- #if __APPLE__
+ #if defined( __APPLE__ )
int mib[4] = {CTL_HW, HW_NCPU, 0, 0};
size_t size = sizeof(processors);
sysctl(mib, 2, &processors, &size, NULL, 0);
- #elif linux
+ #elif defined( __linux__ )
processors = sysconf(_SC_NPROCESSORS_ONLN);
- #elif _WIN32
- SYSTEM_INFO sysinfo; GetSystemInfo( &sysinfo );
+ #elif defined( _WIN32 )
+ GetSystemInfo( &sysinfo );
processors = sysinfo.dwNumberOfProcessors;
#endif
printf(" Number of processors: %d\n", processors);
@@ -181,14 +189,24 @@ config_set(void)
/* File delete command */
config[RM_RF] =
- #if __unix__
+ #if (defined( __APPLE__ ) || defined( __linux__ ))
"rm -rf";
- #if _WIN32
+ #elif defined( _WIN32 )
"del /F /Q /S";
#else
"error: no file delete command";
#endif
+ /* Threads */
+ config[THREADS] =
+ #if (defined( __APPLE__ ) || defined( __linux__ ))
+ "-pthread"; /* Posix threads */
+ #elif ( defined( _WIN32 ) && defined( __GNUC__ ))
+ "-mthreads"; /* MinGW */
+ #else
+ "";
+ #endif
+
/* Make utility */ s=getenv("COMPILER");
if (s && strcmp(s,"GCC")==0) {
config[MAKE_COMMAND] = "make";
@@ -212,7 +230,8 @@ makefile_convert(char * programfilename, char * templatefilename,
trans(&makefiletext, "@exe@", config[EXE]);
trans(&makefiletext, "@outfile@", config[OUTFILE]);
trans(&makefiletext, "@rm_rf@", config[RM_RF]);
- #if _WIN32
+ trans(&makefiletext, "@threads@", config[THREADS]);
+ #if defined( _WIN32 )
trans(&makefiletext, "src/", "src\\");
trans(&makefiletext, "tools/build/", "tools\\build\\");
trans(&makefiletext, "t/01-toolchain/", "t\\01-toolchain\\");
@@ -220,6 +239,9 @@ makefile_convert(char * programfilename, char * templatefilename,
trans(&makefiletext, "t/02-components/", "t\\02-components\\");
trans(&makefiletext, "t/02-components", "t\\02-components");
#endif
+ #if defined( _MSC_VER )
+ trans(&makefiletext, "$(O) ", "$(O)");
+ #endif
printf(" %s: writing to %s\n", programfilename, outputfilename);
squirt(makefiletext, outputfilename);
free(makefiletext);
View
10 c/tools/build/Makefile.in
@@ -28,26 +28,26 @@ t/01-toolchain/01b-timing.exe: t/01-toolchain/01b-timing.c t/Test.h
-$(RM_RF) 01b-timing.obj
t/01-toolchain/01c-threads.exe: t/01-toolchain/01c-threads.c t/Test.h
- $(CC) -pthread $(O) t/01-toolchain/01c-threads.exe t/01-toolchain/01c-threads.c
+ $(CC) $(THREADS) $(O) t/01-toolchain/01c-threads.exe t/01-toolchain/01c-threads.c
-$(RM_RF) 01c-threads.obj
t/02-components/02a-threads.exe: t/02-components/02a-threads.c \
src/threads.h src/threads.c t/Test.h
- $(CC) $(O)t/02-components/02a-threads.exe src/threads.c t/02-components/02a-threads.c
+ $(CC) $(O) t/02-components/02a-threads.exe src/threads.c t/02-components/02a-threads.c
-$(RM_RF) threads.obj 02a-threads.obj
t/02-components/02a-hashtable.exe: t/02-components/02a-hashtable.c \
src/hashtable.h src/hashtable.c t/Test.h
- $(CC) $(O)t/02-components/02a-hashtable.exe src/hashtable.c t/02-components/02a-hashtable.c
+ $(CC) $(O) t/02-components/02a-hashtable.exe src/hashtable.c t/02-components/02a-hashtable.c
-$(RM_RF) hashtable.obj 02a-hashtable.obj
t/02-components/02b-heapmanager.exe: t/02-components/02b-heapmanager.c \
src/heapmanager.h src/heapmanager.c t/Test.h
- $(CC) $(O)t/02-components/02b-heapmanager.exe src/heapmanager.c t/02-components/02b-heapmanager.c
+ $(CC) $(O) t/02-components/02b-heapmanager.exe src/heapmanager.c t/02-components/02b-heapmanager.c
-$(RM_RF) heapmanager.obj 02b-heapmanager.obj
tools/build/prove$(EXE): tools/build/prove.c
- $(CC) $(O)tools/build/prove$(EXE) tools/build/prove.c
+ $(CC) $(O) tools/build/prove$(EXE) tools/build/prove.c
-$(RM_RF) prove.obj
# Note: test executables are named *.exe on all operating systems so

0 comments on commit d7d1a10

Please sign in to comment.
Something went wrong with that request. Please try again.