[haiku-gsoc] Re: XSI semaphore implamentation patch #2

  • From: "Salvatore Benedetto" <emitrax@xxxxxxxxx>
  • To: haiku-gsoc@xxxxxxxxxxxxx
  • Date: Tue, 29 Jul 2008 12:45:00 +0000

Hi there,

2008/7/29 Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>:
>
>>
>> Anyway, if it happens to be a problem, I'll try with another
>> solution.
>
> Well, that indeed doesn't sound like a nice solution, but at least it
> should be good enough for the time being, and to run further tests.
> Anyway, since it's easier to read what you changed instead of the whole
> patch every time, I applied the patch with a few minor changes now in
> r26676; since no one is using the XSI semaphores, it shouldn't hurt
> anyway.

I agree. Thanks for committing it.

> Please have a look at the SVN commit message to see what I changed.
> Most of this has been mentioned previously to you but has not yet been
> picked up by you.

Ok.

>
>> However the software quits thinking that there is not more space
>> available where there actually is.
>> The same behavior does't happened with dd though.
>
> That error could also happen when there is no way to grow the file
> stream anymore - with a single threaded 'dd' this is very unlikely to
> happen, while bonnie++ should be able to run into this much earlier.
> But maybe you want to check where this error happens to be sure that is
> the cause of this; maybe always returning E2BIG would be the better
> alternative for the latter (ie. in case meta data couldn't be allocated
> anymore in contrast to the data stream itself).
>
>> Also some other panic have happened during the test, but not bfs
>> related (at least it seems),
>> like
>> PANIC: _mutex_lock(): double lock of 0x90cc4ed0 by thread 3595
>> where the mutex is vm_cache and thread is grep
>
> A stack crawl would be most helpful in this case.

I'll open a ticket.

>
>> Anyway, I'll investigate on these bugs once this code is complete and
>> committed.
>
> There are still a number of compiler warnings left to be fixed in your
> code. I've fixed those in xsi_sem.cpp due to the missing _kern_*()
> prototypes in syscalls.h, but xsi_semaphore.cpp also produces some;
> please take care of them first.

The only warning I got here are in TRACE calls due to differente type
identifier.
I'll run a fresh recompile to fix those warnings.

>
> Have you written or found any other test suite for XSI that would be
> worth ending up in our repository?

Didn't write any. So far I used bonnie++ plus the two attached tests
found in ltp (linux test project)

Regards,
-- 
Salvatore Benedetto (a.k.a. emitrax)
Student of Computer Engineer
University of Pisa
www.haiku-os.it
/*
 *
 *   Copyright (c) International Business Machines  Corp., 2002
 *
 *   This program is free software;  you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 *   the GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program;  if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

/*
 *  FILE        : sem02.c
 *
 *  DESCRIPTION : The application creates several threads using 
pthread_create().
 *  One thread performs a semop() with the SEM_UNDO flag set. The change in
 *  sempaphore value performed by that semop should be "undone" only when the 
 *  last pthread exits.
 *
 *  EXPECTED OUTPUT:
 *  Waiter, pid = <pid#>
 *  Poster, pid = <pid#>, posting
 *  Poster posted
 *  Poster exiting
 *  Waiter waiting, pid = <pid#>
 *  Waiter done waiting
 *
 *  HISTORY:
 *    written by Dave Olien (oliend@xxxxxxxxxx)
 *    03/06/2002 Robbie Williamson (robbiew@xxxxxxxxxx)
 *      -ported
 *    07/04/2003 Paul Larson (plars@xxxxxxxxxxxxxxxxxxxx)
 *      -ported to LTP
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>
#include <errno.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>

#define KEY IPC_PRIVATE

#define NUMTHREADS 2

void *retval[NUMTHREADS]; 
void * waiter(void *);
void * poster(void *);
void cleanup(void);

char *TCID = "sem02";
int TST_TOTAL = 1;
extern int Tst_count;

struct sembuf Psembuf = {0, -1, SEM_UNDO};
struct sembuf Vsembuf = {0, 1, SEM_UNDO};

union semun {
        int val;                        /* value for SETVAL */
        struct semid_ds *buf;           /* buffer for IPC_STAT & IPC_SET */
        unsigned short *array;          /* array for GETALL & SETALL */
        struct seminfo *ipc_buf;        /* buffer for IPC_INFO */
};


int sem_id;
int err_ret;  /* This is used to determine PASS/FAIL status */
int main(int argc, char **argv)
{
    int i, rc;
    char *msg;
    union semun semunion;
    
    pthread_t pt[NUMTHREADS];
    pthread_attr_t attr;

    /* Create the semaphore set */
    sem_id = semget(KEY, 1, 0666 | IPC_CREAT);
    if (sem_id < 0)
    {
                 printf ("semget failed, errno = %d\n", errno);
                 exit (1);
    }
    /* initialize data  structure associated to the semaphore */
    semunion.val = 1;
    semctl(sem_id, 0, SETVAL, semunion);

    
    /* setup the attributes of the thread        */
    /* set the scope to be system to make sure the threads compete on a  */
    /* global scale for cpu   */
    pthread_attr_init(&attr);
    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);

    err_ret=1;  /* Set initial error value to 1 */ 
    /* Create the threads */
    for (i=0; i<NUMTHREADS; i++)
    {
                 if (i == 0)
                     rc = pthread_create(&pt[i], &attr, waiter, retval[i]);
                 else
                     rc = pthread_create(&pt[i], &attr, poster, retval[i]);
    }

    /* Sleep long enough to see that the other threads do what they are 
supposed to do */
    sleep(20);
    semunion.val = 1;
    semctl(sem_id, 0, IPC_RMID, semunion);
        
    cleanup();
    /* NOT REACHED */
    return 1;
}


/* This thread sleeps 10 seconds then waits on the semaphore.  As long
   as someone has posted on the semaphore, and no undo has taken
   place, the semop should complete and we'll print "Waiter done
   waiting." */
void * waiter(void * foo)
{
    int pid;
    pid = getpid();

    printf("Waiter, pid = %d\n", pid);
    sleep(10);

    printf("Waiter waiting, pid = %d\n", pid);
    semop(sem_id, &Psembuf, 1);
    printf("Waiter done waiting\n");
    err_ret=0; /* If the message above is displayed, the test is a PASS */
    pthread_exit(0);
}

/* This thread immediately posts on the semaphore and then immediately
   exits.  If the *thread* exits, the undo should not happen, and the
   waiter thread which will start waiting on it in 10 seconds, should
   still get it.   */
void * poster(void * foo)
{
    int pid;
   
    pid = getpid();
    printf("Poster, pid = %d, posting\n", pid);
    semop(sem_id, &Vsembuf, 1);
    printf("Poster posted\n");
    printf("Poster exiting\n");
    
    pthread_exit(0);
}

void cleanup(void)
{
}
/*
 *
 *   Copyright (c) International Business Machines  Corp., 2001
 *
 *   This program is free software;  you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 *   the GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program;  if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

/*
 *  FILE        : sem01.c
 *  DESCRIPTION : Creates a semaphore and two processes.  The processes 
 *                each go through a loop where they semdown, delay for a
 *                random amount of time, and semup, so they will almost
 *                always be fighting for control of the semaphore.
 *  HISTORY:
 *    01/15/2001 Paul Larson (plars@xxxxxxxxxx)
 *      -written
 *    11/09/2001 Manoj Iyer (manjo@xxxxxxxxxxxxx)
 *    Modified.
 *    - Removed compiler warnings. 
 *      added exit to the end of function main()
 *
 */

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/sem.h>

union semun {
  int val;
  struct semid_ds *buf;
  unsigned short *array;
};

int verbose = 0;
int loops = 100;
int errors = 0;

int semup(int semid) {
  struct sembuf semops;
  semops.sem_num = 0;
  semops.sem_op = 1;
  semops.sem_flg = SEM_UNDO;
  if(semop(semid, &semops, 1) == -1) {
    perror("semup");
    errors++;
    return 1;
  }
  return 0;
}

int semdown(int semid) {
  struct sembuf semops;
  semops.sem_num = 0;
  semops.sem_op = -1;
  semops.sem_flg = SEM_UNDO;
  if(semop(semid, &semops, 1) == -1) {
    perror("semdown");
    errors++;
    return 1;
  }
  return 0;
}

void delayloop() {
  int delay;
  delay = 1+((100.0*rand())/RAND_MAX);
  if(verbose)
    printf("in delay function for %d microseconds\n",delay);
  usleep(delay);
}

void mainloop(int semid) {
  int i;
  for(i=0;i<loops;i++) {
    if(semdown(semid)) {
      printf("semdown failed\n");
    }
    if(verbose)
      printf("sem is down\n");
    delayloop();
    if(semup(semid)) {
      printf("semup failed\n");
    }
    if(verbose)
      printf("sem is up\n");
  }
}


int main(int argc, char *argv[]) {
  int semid, opt;
  union semun semunion;
  extern char *optarg;
  pid_t pid;
  int chstat;

  while((opt=getopt(argc, argv, "l:vh")) !=EOF) {
    switch((char)opt) {
      case 'l':
        loops = atoi(optarg);
        break;
      case 'v':
        verbose = 1;
        break;
      case 'h':
      default:
        printf("Usage: -l loops [-v]\n");
        exit(1);
    }
  }


  /* set up the semaphore */
  if((semid = semget((key_t)9142, 1, 0666 | IPC_CREAT)) < 0) {
    printf("error in semget()\n");
    exit(-1);
  }
  semunion.val = 1;
  if(semctl(semid, 0, SETVAL, semunion) == -1) {
    printf("error in semctl\n");
  }

  if((pid = fork()) < 0) {
    printf("fork error\n");
    exit(-1);
  }
  if(pid) {
    /* parent */
    srand(pid);
    mainloop(semid);
    waitpid(pid, &chstat, 0);
    if(!WIFEXITED(chstat)) {
      printf("child exited with status\n");
      exit(-1);
    }
    if(semctl(semid, 0, IPC_RMID, semunion) == -1) {
      printf("error in semctl\n");
    }
    if(errors) {
      printf("FAIL: there were %d errors\n",errors);
    } else {
      printf("PASS: error count is 0\n");
    }
    exit(errors);
  } else {
    /* child */
    mainloop(semid);
  }
  exit(0);
}

Other related posts: