2000-02-21 11:24:09 +00:00
|
|
|
/*
|
|
|
|
|
* lcd_sem.c -- semaphore code written for lcdtime and meter to mediate
|
|
|
|
|
* access to the parallel port.
|
|
|
|
|
*
|
|
|
|
|
* Written by Benjamin Tse (blt@mundil.cs.mu.edu.au); August,October 1995
|
|
|
|
|
*
|
|
|
|
|
* Functions in this file:
|
|
|
|
|
* getkey returns the key for the semaphore
|
|
|
|
|
* sem_get create the semaphore (and initialise) if one doesn't exist
|
|
|
|
|
* otherwise return its key
|
|
|
|
|
* sem_wait wait on the semaphore
|
|
|
|
|
* sem_signal signal on the semaphore
|
|
|
|
|
* sem_remove remove the semaphore
|
|
|
|
|
*
|
|
|
|
|
* Legal stuff: At no stage was this program written, assembled or compiled on
|
|
|
|
|
* any computer at the University of Melbourne, Australia. This program is
|
|
|
|
|
* Copyright (C) 1995 Benjamin Tse (blt@mundil.cs.mu.oz.au) and covered by
|
|
|
|
|
* GNU's GPL. In particular, this program is free software and comes WITHOUT
|
|
|
|
|
* ANY WARRANTY.
|
|
|
|
|
*
|
|
|
|
|
* $Id$
|
|
|
|
|
*/
|
|
|
|
|
|
2001-12-25 19:28:54 +00:00
|
|
|
#include <config.h>
|
2000-02-21 11:24:09 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
2000-04-03 22:13:57 +00:00
|
|
|
#include <sys/types.h> /* for semaphore functions */
|
2000-02-21 11:24:09 +00:00
|
|
|
#include <sys/ipc.h>
|
|
|
|
|
#include <sys/sem.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
|
|
#include "lcd_sem.h"
|
|
|
|
|
|
2001-12-25 19:28:54 +00:00
|
|
|
// according to X/OPEN we have to define it ourselves
|
|
|
|
|
//#ifdef _SEM_SEMUN_UNDEFINED
|
|
|
|
|
#ifndef HAVE_UNION_SEMUN
|
2000-11-09 11:12:54 +00:00
|
|
|
union semun {
|
|
|
|
|
int val; /* value for SETVAL */
|
|
|
|
|
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
|
|
|
|
|
unsigned short int *array; /* array for GETALL, SETALL */
|
|
|
|
|
struct seminfo *__buf; /* buffer for IPC_INFO */
|
|
|
|
|
};
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-02-21 11:24:09 +00:00
|
|
|
#define SEMAPHORE "portctrl"
|
2000-03-30 20:20:41 +00:00
|
|
|
#define SEMKEY 0x706f7274 /* semaphore key */
|
2000-04-03 22:13:57 +00:00
|
|
|
#define SEMCOUNT 1 /* number of semaphores to create */
|
|
|
|
|
#define WMODE 0660 /* access permissions */
|
2000-02-21 11:24:09 +00:00
|
|
|
|
|
|
|
|
#define SEM_SIGNAL 0,1,SEM_UNDO
|
|
|
|
|
#define SEM_WAIT 0,-1,SEM_UNDO
|
|
|
|
|
|
|
|
|
|
/* functions local to this file */
|
2000-03-30 20:20:41 +00:00
|
|
|
static key_t getkey (register char *p);
|
|
|
|
|
|
2000-02-21 11:24:09 +00:00
|
|
|
/* global variables */
|
2000-03-30 20:20:41 +00:00
|
|
|
static struct sembuf semaphore_wait = { SEM_WAIT };
|
|
|
|
|
static struct sembuf semaphore_signal = { SEM_SIGNAL };
|
2000-02-21 11:24:09 +00:00
|
|
|
|
|
|
|
|
static char rcsId[] = "$Id$";
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* getkey returns the key for the semaphore
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static key_t
|
2000-03-30 20:20:41 +00:00
|
|
|
getkey (register char *p)
|
2000-02-21 11:24:09 +00:00
|
|
|
{
|
2000-04-03 22:13:57 +00:00
|
|
|
return ((key_t) SEMKEY);
|
2000-02-21 11:24:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* create the semaphore if one doesn't exist and initialise it to 1, else
|
|
|
|
|
* return the semaphore set id
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
2000-03-30 20:20:41 +00:00
|
|
|
sem_get (void)
|
2000-02-21 11:24:09 +00:00
|
|
|
{
|
2000-04-03 22:13:57 +00:00
|
|
|
int semid;
|
|
|
|
|
union semun semval;
|
2000-02-21 11:24:09 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
if ((semid = semget (getkey (SEMAPHORE), SEMCOUNT, IPC_CREAT | IPC_EXCL | WMODE)) < 0) {
|
|
|
|
|
switch (errno) {
|
|
|
|
|
case EEXIST:
|
|
|
|
|
/* semaphore set exists, get id and return it */
|
|
|
|
|
if ((semid = semget (getkey (SEMAPHORE), SEMCOUNT, IPC_EXCL | WMODE)) < 0) {
|
|
|
|
|
perror ("semget");
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
return semid;
|
|
|
|
|
break;
|
|
|
|
|
case EACCES:
|
|
|
|
|
/* don't have permissions for semaphore, need to change key */
|
|
|
|
|
perror ("semget, can't get permissions for semaphore");
|
|
|
|
|
exit (1);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
perror ("semget");
|
|
|
|
|
exit (1);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* initialise semaphore to 1 */
|
|
|
|
|
semval.val = 1;
|
2000-02-21 11:24:09 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
if (semctl (semid, 0, SETVAL, semval) < 0) {
|
|
|
|
|
perror ("setval, can't initialise semaphore");
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
return semid;
|
2000-02-21 11:24:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* wait on the semaphore
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
2000-03-30 20:20:41 +00:00
|
|
|
sem_wait (int sid)
|
2000-02-21 11:24:09 +00:00
|
|
|
{
|
2000-04-03 22:13:57 +00:00
|
|
|
if (semop (sid, &semaphore_wait, 1) < -1) {
|
|
|
|
|
perror (SEMAPHORE);
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
2000-02-21 11:24:09 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
return 0;
|
2000-02-21 11:24:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* signal on the semaphore
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
2000-03-30 20:20:41 +00:00
|
|
|
sem_signal (int sid)
|
2000-02-21 11:24:09 +00:00
|
|
|
{
|
2000-04-03 22:13:57 +00:00
|
|
|
if (semop (sid, &semaphore_signal, 1) < -1) {
|
|
|
|
|
perror (SEMAPHORE);
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
2000-02-21 11:24:09 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
return 0;
|
2000-02-21 11:24:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* remove the semaphore
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int
|
2000-03-30 20:20:41 +00:00
|
|
|
sem_remove (int sid)
|
2000-02-21 11:24:09 +00:00
|
|
|
{
|
2001-12-25 19:28:54 +00:00
|
|
|
#ifdef EIDRM
|
2000-04-03 22:13:57 +00:00
|
|
|
int i;
|
|
|
|
|
union semun dummy;
|
2000-02-21 11:24:09 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
if ((i = semctl (sid, 0, IPC_RMID, dummy)) < 0) {
|
|
|
|
|
switch (i) {
|
|
|
|
|
case EIDRM:
|
|
|
|
|
/* semaphore removed */
|
|
|
|
|
return 0;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
perror ("semctl, removing semaphore");
|
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2001-12-25 19:28:54 +00:00
|
|
|
#endif
|
2000-04-03 22:13:57 +00:00
|
|
|
return 0;
|
2000-02-21 11:24:09 +00:00
|
|
|
}
|