Initialization of semaphores was incorrect. It did not force

the count to "1" to indicate availability.

Interrupt support was added.

Problem where newlib's errno "overrides" that set by system calls
was addressed.

Fixed bug which resulted in all nodes using the same semaphore although
an array of semaphores was allocated.
This commit is contained in:
Joel Sherrill
1995-08-11 14:27:23 +00:00
parent 0e4c603b8e
commit aa9f19454a
4 changed files with 98 additions and 56 deletions

View File

@@ -11,17 +11,8 @@
* OUTPUT PARAMETERS:
* *shmcfg - pointer to SHM Config Table
*
* NOTES: The MP interrupt used is the Runway bus' ability to directly
* address the control registers of up to four CPUs and cause
* interrupts on them.
*
* The following table illustrates the configuration limitations:
*
* BUS MAX
* MODE ENDIAN NODES
* ========= ====== =======
* POLLED BIG 2+
* INTERRUPT BIG 2..4
* NOTES: This driver is capable of supporting a practically unlimited
* number of nodes.
*
* COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
* On-Line Applications Research Corporation (OAR).
@@ -43,13 +34,11 @@
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#define INTERRUPT 0 /* can be interrupt or polling */
#define POLLING 1
shm_config_table BSP_shm_cfgtbl;
int semid;
@@ -58,58 +47,103 @@ void Shm_Cause_interrupt_unix(
rtems_unsigned32 node
);
void Shm_Get_configuration(
rtems_unsigned32 localnode,
shm_config_table **shmcfg
)
void fix_semaphores( void )
{
rtems_unsigned32 maximum_nodes;
int i;
int shmid;
char *shm_addr;
key_t shm_key;
key_t sem_key;
struct sembuf sb;
int status;
int shm_size;
if (getenv("RTEMS_SHM_KEY"))
shm_key = strtol(getenv("RTEMS_SHM_KEY"), 0, 0);
else
#ifdef RTEMS_SHM_KEY
shm_key = RTEMS_SHM_KEY;
#else
shm_key = 0xa000;
#endif
shmid = shmget(shm_key, 16 * KILOBYTE, IPC_CREAT | 0660);
if (getenv("RTEMS_SHM_SIZE"))
shm_size = strtol(getenv("RTEMS_SHM_SIZE"), 0, 0);
else
#ifdef RTEMS_SHM_SIZE
shm_size = RTEMS_SHM_SIZE;
#else
shm_size = 64 * KILOBYTE;
#endif
if (getenv("RTEMS_SHM_SEMAPHORE_KEY"))
sem_key = strtol(getenv("RTEMS_SHM_SEMAPHORE_KEY"), 0, 0);
else
#ifdef RTEMS_SHM_SEMAPHORE_KEY
sem_key = RTEMS_SHM_SEMAPHORE_KEY;
#else
sem_key = 0xa001;
#endif
shmid = shmget(shm_key, shm_size, IPC_CREAT | 0660);
if ( shmid == -1 ) {
fix_syscall_errno(); /* in case of newlib */
perror( "shmget" );
exit( 0 );
rtems_fatal_error_occurred(RTEMS_UNSATISFIED);
}
shm_addr = shmat(shmid, (char *)0, SHM_RND);
if ( shm_addr == (void *)-1 ) {
fix_syscall_errno(); /* in case of newlib */
perror( "shmat" );
exit( 0 );
rtems_fatal_error_occurred(RTEMS_UNSATISFIED);
}
sem_key = 0xa001;
maximum_nodes = Shm_RTEMS_MP_Configuration->maximum_nodes;
semid = semget(sem_key, maximum_nodes + 1, IPC_CREAT | 0660);
if ( semid == -1 ) {
fix_syscall_errno(); /* in case of newlib */
perror( "semget" );
exit( 0 );
rtems_fatal_error_occurred(RTEMS_UNSATISFIED);
}
if ( Shm_Is_master_node() ) {
for ( i=0 ; i <= maximum_nodes ; i++ ) {
sb.sem_op = 1;
sb.sem_num = i;
sb.sem_flg = 0;
status = semop( semid, &sb, 1 );
#if defined(solaris2)
union semun {
int val;
struct semid_ds *buf;
ushort *array;
} help;
help.val = 1;
semctl( semid, i, SETVAL, help );
#endif
#if defined(hpux)
semctl( semid, i, SETVAL, 1 );
#endif
fix_syscall_errno(); /* in case of newlib */
if ( status == -1 ) {
fprintf( stderr, "Sem init failed %d\n", errno ); fflush( stderr );
exit( 0 );
rtems_fatal_error_occurred(RTEMS_UNSATISFIED);
}
}
}
BSP_shm_cfgtbl.base = (vol_u32 *)shm_addr;
BSP_shm_cfgtbl.length = 16 * KILOBYTE;
BSP_shm_cfgtbl.length = shm_size;
}
void Shm_Get_configuration(
rtems_unsigned32 localnode,
shm_config_table **shmcfg
)
{
fix_semaphores();
BSP_shm_cfgtbl.format = SHM_BIG;
BSP_shm_cfgtbl.cause_intr = Shm_Cause_interrupt_unix;
@@ -120,16 +154,16 @@ void Shm_Get_configuration(
BSP_shm_cfgtbl.convert = CPU_swap_u32;
#endif
#if ( POLLING == 1 )
#ifdef INTERRUPT_EXTERNAL_MPCI
BSP_shm_cfgtbl.poll_intr = INTR_MODE;
BSP_shm_cfgtbl.Intr.address = (vol_u32 *) getpid(); /* process id */
BSP_shm_cfgtbl.Intr.value = INTERRUPT_EXTERNAL_MPCI; /* signal to send */
BSP_shm_cfgtbl.Intr.length = LONG;
#else
BSP_shm_cfgtbl.poll_intr = POLLED_MODE;
BSP_shm_cfgtbl.Intr.address = NO_INTERRUPT;
BSP_shm_cfgtbl.Intr.value = NO_INTERRUPT;
BSP_shm_cfgtbl.Intr.length = NO_INTERRUPT;
#else
BSP_shm_cfgtbl.poll_intr = INTR_MODE;
BSP_shm_cfgtbl.Intr.address = 0; /* process id? */
BSP_shm_cfgtbl.Intr.value = 0; /* signal to send? */
BSP_shm_cfgtbl.Intr.length = LONG;
#endif
*shmcfg = &BSP_shm_cfgtbl;

View File

@@ -23,9 +23,14 @@
#include <shm.h>
#include <stdio.h>
#include <signal.h>
void Shm_Cause_interrupt_unix(
rtems_unsigned32 node
)
{
Shm_Interrupt_information *intr;
intr = &Shm_Interrupt_table[node];
kill((pid_t) intr->address, intr->value);
}

View File

@@ -41,8 +41,7 @@ void Shm_Initialize_lock(
Shm_Locked_queue_Control *lq_cb
)
{
lq_cb->lock =
( lq_cb - Shm_Locked_queues ) / sizeof( Shm_Locked_queue_Control );
lq_cb->lock = lq_cb - Shm_Locked_queues;
}
/* Shm_Lock( &lq_cb )
@@ -60,24 +59,25 @@ void Shm_Lock(
struct sembuf sb;
int status;
isr_level = 0;
sb.sem_num = lq_cb->lock;
sb.sem_op = -1;
sb.sem_flg = 0;
rtems_interrupt_disable( isr_level );
Shm_isrstat = isr_level;
while (1) {
status = semop(semid, &sb, 1);
if ( status == 0 )
if ( status >= 0 )
break;
if ( status == -1 && errno == EINTR )
if ( status == -1 ) {
fix_syscall_errno(); /* in case of newlib */
if (errno == EINTR)
continue;
fprintf( stderr, "shm lock(%d %d)\n", status, errno );
exit( 0 );
perror("shm lock");
rtems_fatal_error_occurred(RTEMS_UNSATISFIED);
}
}
}
@@ -95,21 +95,22 @@ void Shm_Unlock(
struct sembuf sb;
int status;
isr_level = 0;
sb.sem_num = lq_cb->lock;
sb.sem_op = 1;
sb.sem_flg = 0;
while (1) {
status = semop(semid, &sb, 1);
if ( status == 0 )
if ( status >= 0 )
break;
if ( status == -1 && errno == EINTR )
continue;
fprintf( stderr, "shm unlock(%d %d)\n", status, errno );
exit( 0 );
if ( status == -1 ) {
fix_syscall_errno(); /* in case of newlib */
if (errno == EINTR)
continue;
perror("shm unlock");
rtems_fatal_error_occurred(RTEMS_UNSATISFIED);
}
}
isr_level = Shm_isrstat;

View File

@@ -25,5 +25,7 @@
void Shm_setvec( void )
{
#ifdef INTERRUPT_EXTERNAL_MPCI
set_vector( Shm_isr, INTERRUPT_EXTERNAL_MPCI, 1 );
#endif
}