forked from Imagelibrary/rtems
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:
@@ -11,17 +11,8 @@
|
|||||||
* OUTPUT PARAMETERS:
|
* OUTPUT PARAMETERS:
|
||||||
* *shmcfg - pointer to SHM Config Table
|
* *shmcfg - pointer to SHM Config Table
|
||||||
*
|
*
|
||||||
* NOTES: The MP interrupt used is the Runway bus' ability to directly
|
* NOTES: This driver is capable of supporting a practically unlimited
|
||||||
* address the control registers of up to four CPUs and cause
|
* number of nodes.
|
||||||
* interrupts on them.
|
|
||||||
*
|
|
||||||
* The following table illustrates the configuration limitations:
|
|
||||||
*
|
|
||||||
* BUS MAX
|
|
||||||
* MODE ENDIAN NODES
|
|
||||||
* ========= ====== =======
|
|
||||||
* POLLED BIG 2+
|
|
||||||
* INTERRUPT BIG 2..4
|
|
||||||
*
|
*
|
||||||
* COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
|
* COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
|
||||||
* On-Line Applications Research Corporation (OAR).
|
* On-Line Applications Research Corporation (OAR).
|
||||||
@@ -43,13 +34,11 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <sys/ipc.h>
|
#include <sys/ipc.h>
|
||||||
#include <sys/shm.h>
|
#include <sys/shm.h>
|
||||||
#include <sys/sem.h>
|
#include <sys/sem.h>
|
||||||
|
|
||||||
#define INTERRUPT 0 /* can be interrupt or polling */
|
|
||||||
#define POLLING 1
|
|
||||||
|
|
||||||
shm_config_table BSP_shm_cfgtbl;
|
shm_config_table BSP_shm_cfgtbl;
|
||||||
|
|
||||||
int semid;
|
int semid;
|
||||||
@@ -58,58 +47,103 @@ void Shm_Cause_interrupt_unix(
|
|||||||
rtems_unsigned32 node
|
rtems_unsigned32 node
|
||||||
);
|
);
|
||||||
|
|
||||||
void Shm_Get_configuration(
|
void fix_semaphores( void )
|
||||||
rtems_unsigned32 localnode,
|
|
||||||
shm_config_table **shmcfg
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
rtems_unsigned32 maximum_nodes;
|
rtems_unsigned32 maximum_nodes;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
int shmid;
|
int shmid;
|
||||||
char *shm_addr;
|
char *shm_addr;
|
||||||
key_t shm_key;
|
key_t shm_key;
|
||||||
key_t sem_key;
|
key_t sem_key;
|
||||||
struct sembuf sb;
|
|
||||||
int status;
|
int status;
|
||||||
|
int shm_size;
|
||||||
|
|
||||||
shm_key = 0xa000;
|
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
|
||||||
|
|
||||||
|
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, 16 * KILOBYTE, IPC_CREAT | 0660);
|
shmid = shmget(shm_key, shm_size, IPC_CREAT | 0660);
|
||||||
if ( shmid == -1 ) {
|
if ( shmid == -1 ) {
|
||||||
|
fix_syscall_errno(); /* in case of newlib */
|
||||||
perror( "shmget" );
|
perror( "shmget" );
|
||||||
exit( 0 );
|
rtems_fatal_error_occurred(RTEMS_UNSATISFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
shm_addr = shmat(shmid, (char *)0, SHM_RND);
|
shm_addr = shmat(shmid, (char *)0, SHM_RND);
|
||||||
if ( shm_addr == (void *)-1 ) {
|
if ( shm_addr == (void *)-1 ) {
|
||||||
|
fix_syscall_errno(); /* in case of newlib */
|
||||||
perror( "shmat" );
|
perror( "shmat" );
|
||||||
exit( 0 );
|
rtems_fatal_error_occurred(RTEMS_UNSATISFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
sem_key = 0xa001;
|
|
||||||
|
|
||||||
maximum_nodes = Shm_RTEMS_MP_Configuration->maximum_nodes;
|
maximum_nodes = Shm_RTEMS_MP_Configuration->maximum_nodes;
|
||||||
semid = semget(sem_key, maximum_nodes + 1, IPC_CREAT | 0660);
|
semid = semget(sem_key, maximum_nodes + 1, IPC_CREAT | 0660);
|
||||||
if ( semid == -1 ) {
|
if ( semid == -1 ) {
|
||||||
|
fix_syscall_errno(); /* in case of newlib */
|
||||||
perror( "semget" );
|
perror( "semget" );
|
||||||
exit( 0 );
|
rtems_fatal_error_occurred(RTEMS_UNSATISFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( Shm_Is_master_node() ) {
|
if ( Shm_Is_master_node() ) {
|
||||||
for ( i=0 ; i <= maximum_nodes ; i++ ) {
|
for ( i=0 ; i <= maximum_nodes ; i++ ) {
|
||||||
sb.sem_op = 1;
|
|
||||||
sb.sem_num = i;
|
#if defined(solaris2)
|
||||||
sb.sem_flg = 0;
|
union semun {
|
||||||
status = semop( semid, &sb, 1 );
|
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 ) {
|
if ( status == -1 ) {
|
||||||
fprintf( stderr, "Sem init failed %d\n", errno ); fflush( stderr );
|
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.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.format = SHM_BIG;
|
||||||
|
|
||||||
BSP_shm_cfgtbl.cause_intr = Shm_Cause_interrupt_unix;
|
BSP_shm_cfgtbl.cause_intr = Shm_Cause_interrupt_unix;
|
||||||
@@ -120,16 +154,16 @@ void Shm_Get_configuration(
|
|||||||
BSP_shm_cfgtbl.convert = CPU_swap_u32;
|
BSP_shm_cfgtbl.convert = CPU_swap_u32;
|
||||||
#endif
|
#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.poll_intr = POLLED_MODE;
|
||||||
BSP_shm_cfgtbl.Intr.address = NO_INTERRUPT;
|
BSP_shm_cfgtbl.Intr.address = NO_INTERRUPT;
|
||||||
BSP_shm_cfgtbl.Intr.value = NO_INTERRUPT;
|
BSP_shm_cfgtbl.Intr.value = NO_INTERRUPT;
|
||||||
BSP_shm_cfgtbl.Intr.length = 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
|
#endif
|
||||||
|
|
||||||
*shmcfg = &BSP_shm_cfgtbl;
|
*shmcfg = &BSP_shm_cfgtbl;
|
||||||
|
|||||||
@@ -23,9 +23,14 @@
|
|||||||
#include <shm.h>
|
#include <shm.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
void Shm_Cause_interrupt_unix(
|
void Shm_Cause_interrupt_unix(
|
||||||
rtems_unsigned32 node
|
rtems_unsigned32 node
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
Shm_Interrupt_information *intr;
|
||||||
|
intr = &Shm_Interrupt_table[node];
|
||||||
|
|
||||||
|
kill((pid_t) intr->address, intr->value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,8 +41,7 @@ void Shm_Initialize_lock(
|
|||||||
Shm_Locked_queue_Control *lq_cb
|
Shm_Locked_queue_Control *lq_cb
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
lq_cb->lock =
|
lq_cb->lock = lq_cb - Shm_Locked_queues;
|
||||||
( lq_cb - Shm_Locked_queues ) / sizeof( Shm_Locked_queue_Control );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shm_Lock( &lq_cb )
|
/* Shm_Lock( &lq_cb )
|
||||||
@@ -60,24 +59,25 @@ void Shm_Lock(
|
|||||||
struct sembuf sb;
|
struct sembuf sb;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
isr_level = 0;
|
|
||||||
|
|
||||||
sb.sem_num = lq_cb->lock;
|
sb.sem_num = lq_cb->lock;
|
||||||
sb.sem_op = -1;
|
sb.sem_op = -1;
|
||||||
sb.sem_flg = 0;
|
sb.sem_flg = 0;
|
||||||
|
|
||||||
rtems_interrupt_disable( isr_level );
|
rtems_interrupt_disable( isr_level );
|
||||||
|
|
||||||
Shm_isrstat = isr_level;
|
Shm_isrstat = isr_level;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
status = semop(semid, &sb, 1);
|
status = semop(semid, &sb, 1);
|
||||||
if ( status == 0 )
|
if ( status >= 0 )
|
||||||
break;
|
break;
|
||||||
if ( status == -1 && errno == EINTR )
|
if ( status == -1 ) {
|
||||||
continue;
|
fix_syscall_errno(); /* in case of newlib */
|
||||||
|
if (errno == EINTR)
|
||||||
fprintf( stderr, "shm lock(%d %d)\n", status, errno );
|
continue;
|
||||||
exit( 0 );
|
perror("shm lock");
|
||||||
|
rtems_fatal_error_occurred(RTEMS_UNSATISFIED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,21 +95,22 @@ void Shm_Unlock(
|
|||||||
struct sembuf sb;
|
struct sembuf sb;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
isr_level = 0;
|
|
||||||
|
|
||||||
sb.sem_num = lq_cb->lock;
|
sb.sem_num = lq_cb->lock;
|
||||||
sb.sem_op = 1;
|
sb.sem_op = 1;
|
||||||
sb.sem_flg = 0;
|
sb.sem_flg = 0;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
status = semop(semid, &sb, 1);
|
status = semop(semid, &sb, 1);
|
||||||
if ( status == 0 )
|
if ( status >= 0 )
|
||||||
break;
|
break;
|
||||||
if ( status == -1 && errno == EINTR )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
fprintf( stderr, "shm unlock(%d %d)\n", status, errno );
|
if ( status == -1 ) {
|
||||||
exit( 0 );
|
fix_syscall_errno(); /* in case of newlib */
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
perror("shm unlock");
|
||||||
|
rtems_fatal_error_occurred(RTEMS_UNSATISFIED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isr_level = Shm_isrstat;
|
isr_level = Shm_isrstat;
|
||||||
|
|||||||
@@ -25,5 +25,7 @@
|
|||||||
|
|
||||||
void Shm_setvec( void )
|
void Shm_setvec( void )
|
||||||
{
|
{
|
||||||
|
#ifdef INTERRUPT_EXTERNAL_MPCI
|
||||||
set_vector( Shm_isr, INTERRUPT_EXTERNAL_MPCI, 1 );
|
set_vector( Shm_isr, INTERRUPT_EXTERNAL_MPCI, 1 );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user