diff options
Diffstat (limited to 'gcc/testsuite/go.test/test/bench/chameneosredux.c')
-rw-r--r-- | gcc/testsuite/go.test/test/bench/chameneosredux.c | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/gcc/testsuite/go.test/test/bench/chameneosredux.c b/gcc/testsuite/go.test/test/bench/chameneosredux.c new file mode 100644 index 000000000..ed78c31d7 --- /dev/null +++ b/gcc/testsuite/go.test/test/bench/chameneosredux.c @@ -0,0 +1,330 @@ +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + http://shootout.alioth.debian.org/ + + contributed by Michael Barker + based on a Java contribution by Luzius Meisser + + convert to C by dualamd +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <pthread.h> + + +enum Colour +{ + blue = 0, + red = 1, + yellow = 2, + Invalid = 3 +}; + +const char* ColourName[] = {"blue", "red", "yellow"}; +const int STACK_SIZE = 32*1024; + +typedef unsigned int BOOL; +const BOOL TRUE = 1; +const BOOL FALSE = 0; + +int CreatureID = 0; + + +enum Colour doCompliment(enum Colour c1, enum Colour c2) +{ + switch (c1) + { + case blue: + switch (c2) + { + case blue: + return blue; + case red: + return yellow; + case yellow: + return red; + default: + goto errlb; + } + case red: + switch (c2) + { + case blue: + return yellow; + case red: + return red; + case yellow: + return blue; + default: + goto errlb; + } + case yellow: + switch (c2) + { + case blue: + return red; + case red: + return blue; + case yellow: + return yellow; + default: + goto errlb; + } + default: + break; + } + +errlb: + printf("Invalid colour\n"); + exit( 1 ); +} + +/* convert integer to number string: 1234 -> "one two three four" */ +char* formatNumber(int n, char* outbuf) +{ + int ochar = 0, ichar = 0; + int i; + char tmp[64]; + + const char* NUMBERS[] = + { + "zero", "one", "two", "three", "four", "five", + "six", "seven", "eight", "nine" + }; + + ichar = sprintf(tmp, "%d", n); + + for (i = 0; i < ichar; i++) + ochar += sprintf( outbuf + ochar, " %s", NUMBERS[ tmp[i] - '0' ] ); + + return outbuf; +} + + +struct MeetingPlace +{ + pthread_mutex_t mutex; + int meetingsLeft; + struct Creature* firstCreature; +}; + +struct Creature +{ + pthread_t ht; + pthread_attr_t stack_att; + + struct MeetingPlace* place; + int count; + int sameCount; + + enum Colour colour; + int id; + + BOOL two_met; + BOOL sameid; +}; + + +void MeetingPlace_Init(struct MeetingPlace* m, int meetings ) +{ + pthread_mutex_init( &m->mutex, 0 ); + m->meetingsLeft = meetings; + m->firstCreature = 0; +} + + +BOOL Meet( struct Creature* cr) +{ + BOOL retval = TRUE; + + struct MeetingPlace* mp = cr->place; + pthread_mutex_lock( &(mp->mutex) ); + + if ( mp->meetingsLeft > 0 ) + { + if ( mp->firstCreature == 0 ) + { + cr->two_met = FALSE; + mp->firstCreature = cr; + } + else + { + struct Creature* first; + enum Colour newColour; + + first = mp->firstCreature; + newColour = doCompliment( cr->colour, first->colour ); + + cr->sameid = cr->id == first->id; + cr->colour = newColour; + cr->two_met = TRUE; + + first->sameid = cr->sameid; + first->colour = newColour; + first->two_met = TRUE; + + mp->firstCreature = 0; + mp->meetingsLeft--; + } + } + else + retval = FALSE; + + pthread_mutex_unlock( &(mp->mutex) ); + return retval; +} + + +void* CreatureThreadRun(void* param) +{ + struct Creature* cr = (struct Creature*)param; + + while (TRUE) + { + if ( Meet(cr) ) + { + while (cr->two_met == FALSE) + sched_yield(); + + if (cr->sameid) + cr->sameCount++; + cr->count++; + } + else + break; + } + + return 0; +} + +void Creature_Init( struct Creature *cr, struct MeetingPlace* place, enum Colour colour ) +{ + cr->place = place; + cr->count = cr->sameCount = 0; + + cr->id = ++CreatureID; + cr->colour = colour; + cr->two_met = FALSE; + + pthread_attr_init( &cr->stack_att ); + pthread_attr_setstacksize( &cr->stack_att, STACK_SIZE ); + pthread_create( &cr->ht, &cr->stack_att, &CreatureThreadRun, (void*)(cr) ); +} + +/* format meeting times of each creature to string */ +char* Creature_getResult(struct Creature* cr, char* str) +{ + char numstr[256]; + formatNumber(cr->sameCount, numstr); + + sprintf( str, "%u%s", cr->count, numstr ); + return str; +} + + +void runGame( int n_meeting, int ncolor, const enum Colour* colours ) +{ + int i; + int total = 0; + char str[256]; + + struct MeetingPlace place; + struct Creature *creatures = (struct Creature*) calloc( ncolor, sizeof(struct Creature) ); + + MeetingPlace_Init( &place, n_meeting ); + + /* print initial color of each creature */ + for (i = 0; i < ncolor; i++) + { + printf( "%s ", ColourName[ colours[i] ] ); + Creature_Init( &(creatures[i]), &place, colours[i] ); + } + printf("\n"); + + /* wait for them to meet */ + for (i = 0; i < ncolor; i++) + pthread_join( creatures[i].ht, 0 ); + + /* print meeting times of each creature */ + for (i = 0; i < ncolor; i++) + { + printf( "%s\n", Creature_getResult(&(creatures[i]), str) ); + total += creatures[i].count; + } + + /* print total meeting times, should equal n_meeting */ + printf( "%s\n\n", formatNumber(total, str) ); + + /* cleaup & quit */ + pthread_mutex_destroy( &place.mutex ); + free( creatures ); +} + + +void printColours( enum Colour c1, enum Colour c2 ) +{ + printf( "%s + %s -> %s\n", + ColourName[c1], + ColourName[c2], + ColourName[doCompliment(c1, c2)] ); +} + +void printColoursTable(void) +{ + printColours(blue, blue); + printColours(blue, red); + printColours(blue, yellow); + printColours(red, blue); + printColours(red, red); + printColours(red, yellow); + printColours(yellow, blue); + printColours(yellow, red); + printColours(yellow, yellow); +} + +int main(int argc, char** argv) +{ + int n = (argc == 2) ? atoi(argv[1]) : 600; + + printColoursTable(); + printf("\n"); + + const enum Colour r1[] = { blue, red, yellow }; + const enum Colour r2[] = { blue, red, yellow, + red, yellow, blue, + red, yellow, red, blue }; + + runGame( n, sizeof(r1) / sizeof(r1[0]), r1 ); + runGame( n, sizeof(r2) / sizeof(r2[0]), r2 ); + + return 0; +} |