Blame tests/pthread.l

Packit f00812
/*
Packit f00812
 * This file is part of flex.
Packit f00812
 * 
Packit f00812
 * Redistribution and use in source and binary forms, with or without
Packit f00812
 * modification, are permitted provided that the following conditions
Packit f00812
 * are met:
Packit f00812
 * 
Packit f00812
 * 1. Redistributions of source code must retain the above copyright
Packit f00812
 *    notice, this list of conditions and the following disclaimer.
Packit f00812
 * 2. Redistributions in binary form must reproduce the above copyright
Packit f00812
 *    notice, this list of conditions and the following disclaimer in the
Packit f00812
 *    documentation and/or other materials provided with the distribution.
Packit f00812
 * 
Packit f00812
 * Neither the name of the University nor the names of its contributors
Packit f00812
 * may be used to endorse or promote products derived from this software
Packit f00812
 * without specific prior written permission.
Packit f00812
 * 
Packit f00812
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
Packit f00812
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
Packit f00812
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
Packit f00812
 * PURPOSE.
Packit f00812
 */
Packit f00812
Packit f00812
%{
Packit f00812
/* A scanner file to build "scanner.c".
Packit f00812
   Input language is any text made of spaces, newlines, and alphanumerics.
Packit f00812
Packit f00812
   We create N_THREADS number of threads. Each thread has it's own scanner.
Packit f00812
   Each thread selects one of the files specified in ARGV, scans it, then
Packit f00812
   closes it. This is repeated N_SCANS numebr of times for each thread.
Packit f00812
Packit f00812
   The idea is to press the scanner to break under threads.
Packit f00812
   If we see  "Scanner Jammed", then we know
Packit f00812
Packit f00812
*/
Packit f00812
#include <stdio.h>
Packit f00812
#include <stdlib.h>
Packit f00812
#include <config.h>
Packit f00812
Packit f00812
#ifdef HAVE_PTHREAD_H
Packit f00812
#include <pthread.h>
Packit f00812
#endif
Packit f00812
Packit f00812
/* A naive test for segfaults when accessing yytext. */
Packit f00812
static int process_text(char* s, yyscan_t  scanner);
Packit f00812
Packit f00812
%}
Packit f00812
Packit f00812
%option 8bit prefix="test"
Packit f00812
%option nounput nomain nodefault noinput
Packit f00812
%option yywrap
Packit f00812
%option reentrant
Packit f00812
%option warn
Packit f00812
Packit f00812
    /* Arbitrary states.*/
Packit f00812
%x STATE_1
Packit f00812
%x STATE_2
Packit f00812
Packit f00812
%%
Packit f00812
Packit f00812
    #define NUMBER 200
Packit f00812
    #define WORD   201
Packit f00812
Packit f00812
<INITIAL>[[:digit:]]+ { BEGIN(STATE_1); process_text(yytext,yyscanner); return NUMBER; }
Packit f00812
<INITIAL>[[:alpha:]]+ { BEGIN(STATE_2); process_text(yytext,yyscanner); return WORD; }
Packit f00812
Packit f00812
<STATE_1>[[:alpha:]]+ { BEGIN(0); process_text(yytext,yyscanner); return WORD; }
Packit f00812
<STATE_1>[[:digit:]]+ { BEGIN(0); process_text(yytext,yyscanner); return NUMBER; }
Packit f00812
Packit f00812
<STATE_2>[[:alpha:]]+ { BEGIN(0); process_text(yytext,yyscanner); return WORD; }
Packit f00812
<STATE_2>[[:digit:]]+ { BEGIN(0); process_text(yytext,yyscanner); return NUMBER; }
Packit f00812
Packit f00812
<INITIAL,STATE_1,STATE_2>" "|\t|\r|\n { process_text(yytext,yyscanner); }
Packit f00812
<INITIAL,STATE_1,STATE_2>[^[:alnum:][:space:]\t\r\n] {
Packit f00812
        /*fprintf(stderr,"*** Error: bad input char '%c'.\n", yytext[0]); */
Packit f00812
        yyterminate();
Packit f00812
    }
Packit f00812
<INITIAL,STATE_1,STATE_2>[[:space:]\r\n]+  { }
Packit f00812
%%
Packit f00812
Packit f00812
int yywrap( yyscan_t  scanner) {
Packit f00812
    (void)scanner;
Packit f00812
    return 1;
Packit f00812
}
Packit f00812
static int process_text(char* s, yyscan_t  scanner)
Packit f00812
{
Packit f00812
    (void)scanner;
Packit f00812
    return (int)(*s) + (int) *(s + yyget_leng(scanner)-1);
Packit f00812
}
Packit f00812
Packit f00812
int main(int ARGC, char *ARGV[]);
Packit f00812
Packit f00812
#ifndef HAVE_LIBPTHREAD
Packit f00812
  int main (int ARGC, char *ARGV[]) {
Packit f00812
    printf(
Packit f00812
       "TEST ABORTED because pthread library not available \n"
Packit f00812
       "-- This is expected on some systems. It is not a flex error.\n" );
Packit f00812
    return 0;
Packit f00812
  }
Packit f00812
#else
Packit f00812
Packit f00812
#define N_THREADS 4
Packit f00812
#define N_SCANS   20
Packit f00812
#define INPUT_FILE "test.input"
Packit f00812
Packit f00812
/* Each thread selects the next file to scan in round-robin fashion.
Packit f00812
   If there are less files than threads, some threads may block. */
Packit f00812
Packit f00812
static pthread_mutex_t next_lock = PTHREAD_MUTEX_INITIALIZER;
Packit f00812
static pthread_mutex_t go_ahead  = PTHREAD_MUTEX_INITIALIZER;
Packit f00812
static int n_files, next_file;
Packit f00812
Packit f00812
static pthread_mutex_t *file_locks;
Packit f00812
static char **filenames;
Packit f00812
Packit f00812
Packit f00812
void * thread_func ( void* arg )
Packit f00812
{
Packit f00812
    int i;
Packit f00812
Packit f00812
    (void)arg;
Packit f00812
Packit f00812
    /* Wait for go-ahead. */
Packit f00812
    pthread_mutex_lock( &go_ahead);
Packit f00812
    pthread_mutex_unlock(&go_ahead);
Packit f00812
Packit f00812
    for( i =0 ; i < N_SCANS ; i++ )
Packit f00812
    {
Packit f00812
        int main(int ARGC, char *ARGV[]);
Packit f00812
Packit f00812
        int next;
Packit f00812
        yyscan_t  scanner;
Packit f00812
        FILE * fp;
Packit f00812
Packit f00812
        pthread_mutex_lock ( &next_lock );
Packit f00812
        next = (next_file++) % n_files;
Packit f00812
        pthread_mutex_unlock ( &next_lock );
Packit f00812
Packit f00812
        pthread_mutex_lock ( &file_locks[ next ] );
Packit f00812
Packit f00812
        yylex_init( &scanner );
Packit f00812
        /*printf("Scanning file %s  #%d\n",filenames[next],i); fflush(stdout); */
Packit f00812
        if((fp = fopen(filenames[next],"r"))==NULL) {
Packit f00812
            perror("fopen");
Packit f00812
            return NULL;
Packit f00812
        }
Packit f00812
        yyset_in(fp,scanner);
Packit f00812
Packit f00812
        while( yylex( scanner) != 0)
Packit f00812
        {
Packit f00812
        }
Packit f00812
        fclose(fp);
Packit f00812
        yylex_destroy(scanner);
Packit f00812
        pthread_mutex_unlock ( &file_locks[ next ] );
Packit f00812
    }
Packit f00812
    return NULL;
Packit f00812
}
Packit f00812
Packit f00812
int main (int ARGC, char *ARGV[])
Packit f00812
{
Packit f00812
    int i;
Packit f00812
    pthread_t threads[N_THREADS];
Packit f00812
Packit f00812
    if( ARGC < 2 ) {
Packit f00812
        fprintf(stderr,"*** Error: No filenames specified.\n");
Packit f00812
        exit(-1);
Packit f00812
    }
Packit f00812
Packit f00812
    /* Allocate and initialize the locks. One for each filename in ARGV. */
Packit f00812
    file_locks = malloc((ARGC-1) * sizeof(pthread_mutex_t));
Packit f00812
    for( i = 0; i < ARGC-1; i++)
Packit f00812
        pthread_mutex_init( &file_locks[i], NULL );
Packit f00812
Packit f00812
    n_files = ARGC -1;
Packit f00812
    filenames = ARGV + 1;
Packit f00812
    next_file = 0;
Packit f00812
Packit f00812
    /* prevent threads from starting until all threads have been created. */
Packit f00812
    pthread_mutex_lock(&go_ahead);
Packit f00812
Packit f00812
    /* Create N threads then wait for them. */
Packit f00812
    for(i =0; i < N_THREADS ; i++ ) {
Packit f00812
        if( pthread_create( &threads[i], NULL, thread_func, NULL) != 0)
Packit f00812
        {
Packit f00812
            fprintf(stderr, "*** Error: pthread_create failed.\n");
Packit f00812
            exit(-1);
Packit f00812
        }
Packit f00812
        printf("Created thread %d.\n",i); fflush(stdout);
Packit f00812
    }
Packit f00812
Packit f00812
    /* Tell threads to begin. */
Packit f00812
    pthread_mutex_unlock(&go_ahead);
Packit f00812
Packit f00812
    for(i =0; i < N_THREADS ; i++ ) {
Packit f00812
        pthread_join ( threads[i], NULL );
Packit f00812
        printf("Thread %d done.\n", i ); fflush(stdout);
Packit f00812
    }
Packit f00812
Packit f00812
    for( i = 0; i < ARGC-1; i++)
Packit f00812
        pthread_mutex_destroy( &file_locks[i] );
Packit f00812
Packit f00812
    pthread_mutex_destroy( &next_lock );
Packit f00812
    pthread_mutex_destroy( &go_ahead );
Packit f00812
    free( file_locks );
Packit f00812
    printf("TEST RETURNING OK.\n");
Packit f00812
    return 0;
Packit f00812
}
Packit f00812
Packit f00812
#endif /* HAVE_LIBPTHREAD */
Packit f00812