Update of /cvsroot/emc/rtapi/src/rtapi
In directory sc8-pr-cvs1:/tmp/cvs-serv3121/src/rtapi
Modified Files:
procfs_macros.h rtai_rtapi.c rtai_ulapi.c rtapi.h
rtapi_common.h rtapi_proc.h sim_rtapi.c sim_ulapi.c ulapi.h
Log Message:
Added module ID, now rtapi_exit() should remove all items allocated by the module. Added a mutex to protect RTAPI internal data from simultaneous access. Basic testing complete, needs more detailed testing.
Index: procfs_macros.h
===================================================================
RCS file: /cvsroot/emc/rtapi/src/rtapi/procfs_macros.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** procfs_macros.h 22 Aug 2003 19:48:38 -0000 1.1
--- procfs_macros.h 24 Aug 2003 09:38:25 -0000 1.2
***************
*** 59,62 ****
return len // no ";"
! #endif /* PROC_FS */
! #endif /* PROCFS_MACROS_H */
--- 59,62 ----
return len // no ";"
! #endif /* PROC_FS */
! #endif /* PROCFS_MACROS_H */
Index: rtai_rtapi.c
===================================================================
RCS file: /cvsroot/emc/rtapi/src/rtapi/rtai_rtapi.c,v
retrieving revision 1.30
retrieving revision 1.31
diff -C2 -d -r1.30 -r1.31
*** rtai_rtapi.c 20 Aug 2003 03:16:21 -0000 1.30
--- rtai_rtapi.c 24 Aug 2003 09:38:25 -0000 1.31
***************
*** 54,58 ****
#include <linux/kernel.h>
#include <linux/slab.h> /* replaces malloc.h in recent kernels */
- #include <linux/proc_fs.h> /* proc_fs functions */
#include <linux/ctype.h> /* isdigit */
#include <linux/delay.h> /* udelay */
--- 54,57 ----
***************
*** 80,86 ****
/* resource data unique to kernel space */
[...1528 lines suppressed...]
! return RTAPI_INVAL;
! }
! /* found the irq */
! irq_id = n;
! irq = &(irq_array[n]);
! /* get rid of the handler */
! rt_shutdown_irq(irq_num);
! retval = rt_free_global_irq(irq_num);
if (retval != 0) {
return RTAPI_FAIL;
}
! /* update data */
! irq->irq_num = 0;
! irq->owner = 0;
! irq->handler = NULL;
rtapi_data->irq_count--;
rtapi_print_msg(RTAPI_MSG_DBG,
! "RTAPI: handler for IRQ %d deleted\n", irq_num);
return RTAPI_SUCCESS;
}
Index: rtai_ulapi.c
===================================================================
RCS file: /cvsroot/emc/rtapi/src/rtapi/rtai_ulapi.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -d -r1.8 -r1.9
*** rtai_ulapi.c 20 Aug 2003 03:16:21 -0000 1.8
--- rtai_ulapi.c 24 Aug 2003 09:38:25 -0000 1.9
***************
*** 46,49 ****
--- 46,50 ----
#include <stdio.h> /* sprintf() */
+ #include <string.h> /* strcpy, etc. */
#include <stddef.h> /* NULL, needed for rtai_shm.h */
#include <unistd.h> /* open(), close() */
***************
*** 58,69 ****
#include "rtapi_common.h" /* private RTAPI/ULAPI decls */
/* resource data unique to this process */
! static void *shmem_addr_array[RTAPI_MAX_SHMEMS+1];
! static int fifo_fd_array[RTAPI_MAX_FIFOS+1];
! int ulapi_init(void)
{
! int n;
/* get shared memory block from OS and save its address */
--- 59,86 ----
#include "rtapi_common.h" /* private RTAPI/ULAPI decls */
+ /* the following are internal functions that do the real work associated
+ with deleting resources. They do not check the mutex that protects
+ the internal data structures. When someone calls a ulapi_xxx_delete()
+ function, the ulapi funct gets the mutex before calling one of these
+ internal functions. When internal code that already has the mutex
+ needs to delete something, it calls these functions directly.
+ */
+
+ static int shmem_delete(int shmem_id, int module_id);
+ static int fifo_delete(int fifo_id, int module_id);
+
/* resource data unique to this process */
! static void *shmem_addr_array[RTAPI_MAX_SHMEMS + 1];
! static int fifo_fd_array[RTAPI_MAX_FIFOS + 1];
! /***********************************************************************
! * GENERAL PURPOSE FUNCTIONS *
! ************************************************************************/
!
! int ulapi_init(char *modname)
{
! int n, module_id;
! module_data *module;
/* get shared memory block from OS and save its address */
***************
*** 73,78 ****
}
/* perform a global init if needed */
! init_rtapi_data ( rtapi_data );
/* set up local pointers to global data */
task_array = rtapi_data->task_array;
shmem_array = rtapi_data->shmem_array;
--- 90,96 ----
}
/* perform a global init if needed */
! init_rtapi_data(rtapi_data);
/* set up local pointers to global data */
+ module_array = rtapi_data->module_array;
task_array = rtapi_data->task_array;
shmem_array = rtapi_data->shmem_array;
***************
*** 84,116 ****
shmem_addr_array[n] = NULL;
}
! /* update module count */
! mutex_get ( &(rtapi_data->mutex) );
rtapi_data->ul_module_count++;
! mutex_give ( &(rtapi_data->mutex) );
! return ULAPI_SUCCESS;
}
! int ulapi_exit(void)
{
if (rtapi_data == NULL) {
! /* no inited */
return ULAPI_INVAL;
}
! /* do cleanup here, nothing implemented yet */
!
! /* update module count */
! mutex_get ( &(rtapi_data->mutex) );
rtapi_data->ul_module_count--;
! mutex_give ( &(rtapi_data->mutex) );
return ULAPI_SUCCESS;
}
/***********************************************************************
* SHARED MEMORY RELATED FUNCTIONS *
************************************************************************/
! int ulapi_shmem_new(int key, unsigned long int size)
{
int n;
--- 102,305 ----
shmem_addr_array[n] = NULL;
}
!
! /* get the mutex */
! mutex_get(&(rtapi_data->mutex));
! /* find empty spot in module array */
! n = 1;
! while ((n <= RTAPI_MAX_MODULES) && (module_array[n].state != NO_MODULE)) {
! n++;
! }
! if (n > RTAPI_MAX_MODULES) {
! /* no room */
! mutex_give(&(rtapi_data->mutex));
! return ULAPI_LIMIT;
! }
! /* we have space for the module */
! module_id = n;
! module = &(module_array[n]);
! /* update module data */
! module->state = USERSPACE;
! if (modname != NULL) {
! /* use name supplied by caller */
! snprintf(module->name, RTAPI_MODULE_NAME_LEN - 1, "%s", modname);
! module->name[RTAPI_MODULE_NAME_LEN - 1] = '\0';
! } else {
! /* make up a name */
! snprintf(module->name, RTAPI_MODULE_NAME_LEN - 1, "ULMOD%03d", module_id);
! }
rtapi_data->ul_module_count++;
! mutex_give(&(rtapi_data->mutex));
! return module_id;
}
! int ulapi_exit(int module_id)
{
+ module_data *module;
+ int n;
+
if (rtapi_data == NULL) {
! /* not inited */
return ULAPI_INVAL;
}
! /* validate module ID */
! if ((module_id < 1) || (module_id > RTAPI_MAX_MODULES)) {
! return ULAPI_BADID;
! }
! /* get mutex */
! mutex_get(&(rtapi_data->mutex));
! /* point to the module's data */
! module = &(module_array[module_id]);
! /* check module status */
! if (module->state != USERSPACE) {
! /* not an active user space module */
! mutex_give(&(rtapi_data->mutex));
! return ULAPI_INVAL;
! }
! /* clean up any mess left behind by the module */
! for (n = 1; n <= RTAPI_MAX_SHMEMS; n++) {
! if (test_bit(module_id, shmem_array[n].bitmap)) {
! fprintf(stderr,
! "ULAPI: WARNING: module '%s' failed to delete shmem %02d\n",
! module->name, n);
! shmem_delete(n, module_id);
! }
! }
! for (n = 1; n <= RTAPI_MAX_FIFOS; n++) {
! if ((fifo_array[n].reader == module_id) ||
! (fifo_array[n].writer == module_id)) {
! fprintf(stderr,
! "ULAPI: WARNING: module '%s' failed to delete fifo %02d\n",
! module->name, n);
! fifo_delete(n, module_id);
! }
! }
! /* update module data */
! module->state = NO_MODULE;
! module->name[0] = '\0';
rtapi_data->ul_module_count--;
! /* unmap shared memory block */
! mutex_give(&(rtapi_data->mutex));
! rtai_free(RTAPI_KEY, rtapi_data);
return ULAPI_SUCCESS;
}
+ void ulapi_printall ( void )
+ {
+ module_data *modules;
+ task_data *tasks;
+ shmem_data *shmems;
+ sem_data *sems;
+ fifo_data *fifos;
+ irq_data *irqs;
+ int n, m;
+
+ if ( rtapi_data == NULL ) {
+ printf ( "rtapi_data = NULL, not initialized\n" );
+ return;
+ }
+ printf ( "rtapi_data = %p\n", rtapi_data );
+ printf ( " magic = %d\n", rtapi_data->magic );
+ printf ( " mutex = %d\n", rtapi_data->mutex );
+ printf ( " rt_module_count = %d\n", rtapi_data->rt_module_count );
+ printf ( " ul_module_count = %d\n", rtapi_data->ul_module_count );
+ printf ( " task_count = %d\n", rtapi_data->task_count );
+ printf ( " shmem_count = %d\n", rtapi_data->shmem_count );
+ printf ( " sem_count = %d\n", rtapi_data->sem_count );
+ printf ( " fifo_count = %d\n", rtapi_data->fifo_count );
+ printf ( " irq_countc = %d\n", rtapi_data->irq_count );
+ printf ( " timer_running = %d\n", rtapi_data->timer_running );
+ printf ( " timer_period = %ld\n", rtapi_data->timer_period );
+ modules = &(rtapi_data->module_array[0]);
+ tasks = &(rtapi_data->task_array[0]);
+ shmems = &(rtapi_data->shmem_array[0]);
+ sems = &(rtapi_data->sem_array[0]);
+ fifos = &(rtapi_data->fifo_array[0]);
+ irqs = &(rtapi_data->irq_array[0]);
+ printf ( " module array = %p\n", modules );
+ printf ( " task array = %p\n", tasks );
+ printf ( " shmem array = %p\n", shmems );
+ printf ( " sem array = %p\n", sems );
+ printf ( " fifo array = %p\n", fifos );
+ printf ( " irq array = %p\n", irqs );
+ for ( n = 0 ; n <= RTAPI_MAX_MODULES ; n++ ) {
+ if ( modules[n].state != NO_MODULE ) {
+ printf ( " module %02d\n", n );
+ printf ( " state = %d\n", modules[n].state );
+ printf ( " name = %p\n", modules[n].name );
+ printf ( " name = '%s'\n", modules[n].name );
+ }
+ }
+ for ( n = 0 ; n <= RTAPI_MAX_TASKS ; n++ ) {
+ if ( tasks[n].state != EMPTY ) {
+ printf ( " task %02d\n", n );
+ printf ( " state = %d\n", tasks[n].state );
+ printf ( " prio = %d\n", tasks[n].prio );
+ printf ( " owner = %d\n", tasks[n].owner );
+ printf ( " code = %p\n", tasks[n].taskcode );
+ }
+ }
+ for ( n = 0 ; n <= RTAPI_MAX_SHMEMS ; n++ ) {
+ if ( shmems[n].key != 0 ) {
+ printf ( " shmem %02d\n", n );
+ printf ( " key = %d\n", shmems[n].key );
+ printf ( " rtusers = %d\n", shmems[n].rtusers );
+ printf ( " ulusers = %d\n", shmems[n].ulusers );
+ printf ( " size = %ld\n", shmems[n].size );
+ printf ( " bitmap = " );
+ for ( m = 0 ; m <= RTAPI_MAX_MODULES ; m++ ) {
+ if ( test_bit ( m, shmems[n].bitmap ) ) {
+ putchar ( '1' );
+ }
+ else {
+ putchar ( '0' );
+ }
+ }
+ putchar ( '\n' );
+ }
+ }
+ for ( n = 0 ; n <= RTAPI_MAX_SEMS ; n++ ) {
+ if ( sems[n].key != 0 ) {
+ printf ( " sem %02d\n", n );
+ printf ( " key = %d\n", sems[n].key );
+ printf ( " users = %d\n", sems[n].users );
+ printf ( " bitmap = " );
+ for ( m = 0 ; m <= RTAPI_MAX_MODULES ; m++ ) {
+ if ( test_bit ( m, sems[n].bitmap ) ) {
+ putchar ( '1' );
+ }
+ else {
+ putchar ( '0' );
+ }
+ }
+ putchar ( '\n' );
+ }
+ }
+ for ( n = 0 ; n <= RTAPI_MAX_FIFOS ; n++ ) {
+ if ( fifos[n].state != UNUSED ) {
+ printf ( " fifo %02d\n", n );
+ printf ( " state = %d\n", fifos[n].state );
+ printf ( " key = %d\n", fifos[n].key );
+ printf ( " reader = %d\n", fifos[n].reader );
+ printf ( " writer = %d\n", fifos[n].writer );
+ printf ( " size = %ld\n", fifos[n].size );
+ }
+ }
+ for ( n = 0 ; n <= RTAPI_MAX_IRQS ; n++ ) {
+ if ( irqs[n].irq_num != 0 ) {
+ printf ( " irq %02d\n", n );
+ printf ( " irq_num = %d\n", irqs[n].irq_num );
+ printf ( " owner = %d\n", irqs[n].owner );
+ printf ( " handler = %p\n", irqs[n].handler );
+ }
+ }
+ }
+
/***********************************************************************
* SHARED MEMORY RELATED FUNCTIONS *
************************************************************************/
! int ulapi_shmem_new(int key, int module_id, unsigned long int size)
{
int n;
***************
*** 119,128 ****
/* key must be non-zero, and also cannot match the key that RTAPI uses */
! if (( key == 0 ) || ( key == RTAPI_KEY )) {
return ULAPI_INVAL;
}
/* check if a block is already open for this key */
! for ( n = 1; n <= RTAPI_MAX_SHMEMS ; n++ ) {
! if ( shmem_array[n].key == key ) {
/* found a match */
shmem_id = n;
--- 308,328 ----
/* key must be non-zero, and also cannot match the key that RTAPI uses */
! if ((key == 0) || (key == RTAPI_KEY)) {
! return ULAPI_INVAL;
! }
! /* get the mutex */
! mutex_get(&(rtapi_data->mutex));
! /* validate module_id */
! if ((module_id < 1) || (module_id > RTAPI_MAX_MODULES)) {
! mutex_give(&(rtapi_data->mutex));
! return ULAPI_INVAL;
! }
! if (module_array[module_id].state != USERSPACE) {
! mutex_give(&(rtapi_data->mutex));
return ULAPI_INVAL;
}
/* check if a block is already open for this key */
! for (n = 1; n <= RTAPI_MAX_SHMEMS; n++) {
! if (shmem_array[n].key == key) {
/* found a match */
shmem_id = n;
***************
*** 130,149 ****
/* is it big enough? */
if (shmem->size < size) {
return ULAPI_INVAL;
}
! /* yes, has this process already mapped it? */
! if (shmem_addr_array[shmem_id] != 0 ) {
! /* can't map twice */
! return ULAPI_FAIL;
}
/* no, map it */
shmem_addr_array[shmem_id] = rtai_malloc(key, shmem->size);
if (shmem_addr_array[shmem_id] == NULL) {
! /* map failed */
! return ULAPI_NOMEM;
}
/* update usage data */
shmem->ulusers++;
/* done */
return shmem_id;
}
--- 330,353 ----
/* is it big enough? */
if (shmem->size < size) {
+ mutex_give(&(rtapi_data->mutex));
return ULAPI_INVAL;
}
! /* is this module already using it? */
! if (test_bit(module_id, shmem->bitmap)) {
! mutex_give(&(rtapi_data->mutex));
! return ULAPI_INVAL;
}
/* no, map it */
shmem_addr_array[shmem_id] = rtai_malloc(key, shmem->size);
if (shmem_addr_array[shmem_id] == NULL) {
! /* map failed */
! mutex_give(&(rtapi_data->mutex));
! return ULAPI_NOMEM;
}
/* update usage data */
+ set_bit(module_id, shmem->bitmap);
shmem->ulusers++;
/* done */
+ mutex_give(&(rtapi_data->mutex));
return shmem_id;
}
***************
*** 151,160 ****
/* find empty spot in shmem array */
n = 1;
! while ((n <= RTAPI_MAX_SHMEMS) &&
! (shmem_array[n].key != 0)) {
n++;
}
if (n > RTAPI_MAX_SHMEMS) {
/* no room */
return ULAPI_LIMIT;
}
--- 355,364 ----
/* find empty spot in shmem array */
n = 1;
! while ((n <= RTAPI_MAX_SHMEMS) && (shmem_array[n].key != 0)) {
n++;
}
if (n > RTAPI_MAX_SHMEMS) {
/* no room */
+ mutex_give(&(rtapi_data->mutex));
return ULAPI_LIMIT;
}
***************
*** 165,171 ****
shmem_addr_array[shmem_id] = rtai_malloc(key, size);
if (shmem_addr_array[shmem_id] == NULL) {
return ULAPI_NOMEM;
}
! /* fill in the data */
shmem->key = key;
shmem->rtusers = 0;
--- 369,377 ----
shmem_addr_array[shmem_id] = rtai_malloc(key, size);
if (shmem_addr_array[shmem_id] == NULL) {
+ mutex_give(&(rtapi_data->mutex));
return ULAPI_NOMEM;
}
! /* the block has been created, update data */
! set_bit(module_id, shmem->bitmap);
shmem->key = key;
shmem->rtusers = 0;
***************
*** 174,185 ****
rtapi_data->shmem_count++;
/* done */
return shmem_id;
}
! int ulapi_shmem_delete(int shmem_id)
{
! shmem_data *shmem;
/* validate shmem ID */
if ((shmem_id < 1) || (shmem_id > RTAPI_MAX_SHMEMS)) {
--- 380,402 ----
rtapi_data->shmem_count++;
/* done */
+ mutex_give(&(rtapi_data->mutex));
return shmem_id;
}
! int ulapi_shmem_delete(int shmem_id, int module_id)
{
! int retval;
+ mutex_get(&(rtapi_data->mutex));
+ retval = shmem_delete(shmem_id, module_id);
+ mutex_give(&(rtapi_data->mutex));
+ return retval;
+ }
+
+
+ int shmem_delete(int shmem_id, int module_id)
+ {
+ shmem_data *shmem;
/* validate shmem ID */
if ((shmem_id < 1) || (shmem_id > RTAPI_MAX_SHMEMS)) {
***************
*** 189,202 ****
shmem = &(shmem_array[shmem_id]);
/* is the block valid? */
! if (shmem->key == 0 ) {
return ULAPI_BADID;
}
/* unmap the block */
rtai_free(shmem->key, shmem_addr_array[shmem_id]);
shmem_addr_array[shmem_id] = NULL;
- /* update data */
- shmem->ulusers--;
/* is somebody else still using the block? */
! if ((shmem->ulusers > 0 ) || (shmem->rtusers > 0 )) {
/* yes, we're done for now */
return ULAPI_SUCCESS;
--- 406,431 ----
shmem = &(shmem_array[shmem_id]);
/* is the block valid? */
! if (shmem->key == 0) {
return ULAPI_BADID;
}
+ /* validate module_id */
+ if ((module_id < 1) || (module_id > RTAPI_MAX_MODULES)) {
+ return ULAPI_INVAL;
+ }
+ if (module_array[module_id].state != USERSPACE) {
+ return ULAPI_INVAL;
+ }
+ /* is this module using the block? */
+ if (test_bit(module_id, shmem->bitmap) == 0) {
+ return ULAPI_INVAL;
+ }
+ /* OK, we're no longer using it */
+ clear_bit(module_id, shmem->bitmap);
+ shmem->ulusers--;
/* unmap the block */
rtai_free(shmem->key, shmem_addr_array[shmem_id]);
shmem_addr_array[shmem_id] = NULL;
/* is somebody else still using the block? */
! if ((shmem->ulusers > 0) || (shmem->rtusers > 0)) {
/* yes, we're done for now */
return ULAPI_SUCCESS;
***************
*** 217,221 ****
}
/* is the block mapped? */
! if (shmem_addr_array[shmem_id] == NULL ) {
return ULAPI_BADID;
}
--- 446,450 ----
}
/* is the block mapped? */
! if (shmem_addr_array[shmem_id] == NULL) {
return ULAPI_BADID;
}
***************
*** 226,230 ****
! int ulapi_fifo_new(int key, unsigned long int size, char mode)
{
enum { DEVSTR_LEN = 256 };
--- 455,463 ----
! /***********************************************************************
! * FIFO RELATED FUNCTIONS *
! ************************************************************************/
!
! int ulapi_fifo_new(int key, int module_id, unsigned long int size, char mode)
{
enum { DEVSTR_LEN = 256 };
***************
*** 235,243 ****
/* key must be non-zero */
! if ( key == 0 ) {
return ULAPI_INVAL;
}
/* mode must be "R" or "W" */
! if (( mode != 'R' ) && ( mode != 'W' )) {
return ULAPI_INVAL;
}
--- 468,476 ----
/* key must be non-zero */
! if (key == 0) {
return ULAPI_INVAL;
}
/* mode must be "R" or "W" */
! if ((mode != 'R') && (mode != 'W')) {
return ULAPI_INVAL;
}
***************
*** 245,254 ****
if (mode == 'R') {
flags = O_RDONLY;
! }
! else /* mode == 'W' */ {
flags = O_WRONLY;
}
/* check if a fifo already exists for this key */
! for ( n = 1; n <= RTAPI_MAX_FIFOS ; n++ ) {
if ((fifo_array[n].state != UNUSED) && (fifo_array[n].key == key)) {
/* found a match */
--- 478,498 ----
if (mode == 'R') {
flags = O_RDONLY;
! } else { /* mode == 'W' */
!
flags = O_WRONLY;
}
+ /* get the mutex */
+ mutex_get(&(rtapi_data->mutex));
+ /* validate module_id */
+ if ((module_id < 1) || (module_id > RTAPI_MAX_MODULES)) {
+ mutex_give(&(rtapi_data->mutex));
+ return ULAPI_INVAL;
+ }
+ if (module_array[module_id].state != USERSPACE) {
+ mutex_give(&(rtapi_data->mutex));
+ return ULAPI_INVAL;
+ }
/* check if a fifo already exists for this key */
! for (n = 1; n <= RTAPI_MAX_FIFOS; n++) {
if ((fifo_array[n].state != UNUSED) && (fifo_array[n].key == key)) {
/* found a match */
***************
*** 256,261 ****
fifo = &(fifo_array[n]);
/* is the desired mode available */
! if ( mode == 'R' ) {
! if ( fifo->state & HAS_READER ) {
return ULAPI_BUSY;
}
--- 500,506 ----
fifo = &(fifo_array[n]);
/* is the desired mode available */
! if (mode == 'R') {
! if (fifo->state & HAS_READER) {
! mutex_give(&(rtapi_data->mutex));
return ULAPI_BUSY;
}
***************
*** 266,277 ****
if (fifo_fd_array[fifo_id] < 0) {
/* open failed */
return ULAPI_NOTFND;
}
/* fifo opened, update status */
fifo->state |= HAS_READER;
return fifo_id;
! }
! else /* mode == 'W' */ {
! if ( fifo->state & HAS_WRITER ) {
return ULAPI_BUSY;
}
--- 511,526 ----
if (fifo_fd_array[fifo_id] < 0) {
/* open failed */
+ mutex_give(&(rtapi_data->mutex));
return ULAPI_NOTFND;
}
/* fifo opened, update status */
fifo->state |= HAS_READER;
+ fifo->reader = module_id;
+ mutex_give(&(rtapi_data->mutex));
return fifo_id;
! } else { /* mode == 'W' */
!
! if (fifo->state & HAS_WRITER) {
! mutex_give(&(rtapi_data->mutex));
return ULAPI_BUSY;
}
***************
*** 282,289 ****
--- 531,541 ----
if (fifo_fd_array[fifo_id] < 0) {
/* open failed */
+ mutex_give(&(rtapi_data->mutex));
return ULAPI_NOTFND;
}
/* fifo opened, update status */
fifo->state |= HAS_WRITER;
+ fifo->writer = module_id;
+ mutex_give(&(rtapi_data->mutex));
return fifo_id;
}
***************
*** 292,301 ****
/* find empty spot in fifo array */
n = 1;
! while ((n <= RTAPI_MAX_FIFOS) &&
! (fifo_array[n].state != UNUSED)) {
n++;
}
if (n > RTAPI_MAX_FIFOS) {
/* no room */
return ULAPI_LIMIT;
}
--- 544,553 ----
/* find empty spot in fifo array */
n = 1;
! while ((n <= RTAPI_MAX_FIFOS) && (fifo_array[n].state != UNUSED)) {
n++;
}
if (n > RTAPI_MAX_FIFOS) {
/* no room */
+ mutex_give(&(rtapi_data->mutex));
return ULAPI_LIMIT;
}
***************
*** 309,320 ****
if (fifo_fd_array[fifo_id] < 0) {
/* open failed */
return ULAPI_NOTFND;
}
/* the fifo has been created, update data */
! if ( mode == 'R' ) {
fifo->state = HAS_READER;
! }
! else /* mode == 'W' */ {
fifo->state = HAS_WRITER;
}
fifo->key = key;
--- 561,575 ----
if (fifo_fd_array[fifo_id] < 0) {
/* open failed */
+ mutex_give(&(rtapi_data->mutex));
return ULAPI_NOTFND;
}
/* the fifo has been created, update data */
! if (mode == 'R') {
fifo->state = HAS_READER;
! fifo->reader = module_id;
! } else { /* mode == 'W' */
!
fifo->state = HAS_WRITER;
+ fifo->writer = module_id;
}
fifo->key = key;
***************
*** 322,330 ****
rtapi_data->fifo_count++;
/* done */
return fifo_id;
}
! int ulapi_fifo_delete(int fifo_id, char mode)
{
fifo_data *fifo;
--- 577,597 ----
rtapi_data->fifo_count++;
/* done */
+ mutex_give(&(rtapi_data->mutex));
return fifo_id;
}
! int ulapi_fifo_delete(int fifo_id, int module_id)
! {
! int retval;
!
! mutex_get(&(rtapi_data->mutex));
! retval = fifo_delete(fifo_id, module_id);
! mutex_give(&(rtapi_data->mutex));
! return retval;
! }
!
!
! static int fifo_delete(int fifo_id, int module_id)
{
fifo_data *fifo;
***************
*** 337,371 ****
fifo = &(fifo_array[fifo_id]);
/* is the fifo valid? */
! if (fifo->state == UNUSED ) {
return ULAPI_BADID;
}
! /* check fifo state */
! if ( mode == 'R' ) {
! if (( fifo->state & HAS_READER ) == 0 ) {
! return ULAPI_INVAL;
! }
! /* close the fifo */
! if (close(fifo_id) < 0) {
! return ULAPI_NOTFND;
! }
! /* update fifo state */
fifo->state &= ~HAS_READER;
}
! else if ( mode == 'W' ) {
! if (( fifo->state & HAS_WRITER ) == 0 ) {
! return ULAPI_INVAL;
! }
! /* close the fifo */
! if (close(fifo_id) < 0) {
! return ULAPI_NOTFND;
! }
! /* update fifo state */
fifo->state &= ~HAS_WRITER;
}
! else {
! return ULAPI_INVAL;
}
/* is somebody else still using the fifo */
! if ( fifo->state != UNUSED ) {
/* yes, done for now */
return ULAPI_SUCCESS;
--- 604,636 ----
fifo = &(fifo_array[fifo_id]);
/* is the fifo valid? */
! if (fifo->state == UNUSED) {
return ULAPI_BADID;
}
! /* validate module_id */
! if ((module_id < 1) || (module_id > RTAPI_MAX_MODULES)) {
! return ULAPI_INVAL;
! }
! if (module_array[module_id].state != USERSPACE) {
! return ULAPI_INVAL;
! }
! /* is this module using the fifo? */
! if ((fifo->reader != module_id) && (fifo->writer != module_id)) {
! return ULAPI_INVAL;
! }
! /* update fifo state */
! if (fifo->reader == module_id) {
fifo->state &= ~HAS_READER;
+ fifo->reader = 0;
}
! if (fifo->writer == module_id) {
fifo->state &= ~HAS_WRITER;
+ fifo->writer = 0;
}
! /* close the fifo */
! if (close(fifo_id) < 0) {
! return ULAPI_NOTFND;
}
/* is somebody else still using the fifo */
! if (fifo->state != UNUSED) {
/* yes, done for now */
return ULAPI_SUCCESS;
***************
*** 393,397 ****
fifo = &(fifo_array[fifo_id]);
/* is the fifo valid? */
! if ((fifo->state & HAS_READER) == 0 ) {
return ULAPI_BADID;
}
--- 658,662 ----
fifo = &(fifo_array[fifo_id]);
/* is the fifo valid? */
! if ((fifo->state & HAS_READER) == 0) {
return ULAPI_BADID;
}
***************
*** 417,421 ****
fifo = &(fifo_array[fifo_id]);
/* is the fifo valid? */
! if ((fifo->state & HAS_WRITER) == 0 ) {
return ULAPI_BADID;
}
--- 682,686 ----
fifo = &(fifo_array[fifo_id]);
/* is the fifo valid? */
! if ((fifo->state & HAS_WRITER) == 0) {
return ULAPI_BADID;
}
Index: rtapi.h
===================================================================
RCS file: /cvsroot/emc/rtapi/src/rtapi/rtapi.h,v
retrieving revision 1.28
retrieving revision 1.29
diff -C2 -d -r1.28 -r1.29
*** rtapi.h 22 Aug 2003 19:48:38 -0000 1.28
--- rtapi.h 24 Aug 2003 09:38:25 -0000 1.29
***************
*** 65,82 ****
/** 'rtapi_init() sets up the RTAPI. It must be called by any module
! that intends to use the API, before any other RTAPI calls. Returns
! a status code, as defined above. Increments a usage count. Call
! only from within init/cleanup code, not from realtime tasks.
*/
! extern int rtapi_init(void);
/** 'rtapi_exit()' shuts down and cleans up the RTAPI. It must be
called prior to exit by any module that called rtapi_init.
! Returns a status code. Decrements the usage count maintained
! by rtapi_init. Call only from within init/cleanup code, not
! from realtime tasks.
*/
! extern int rtapi_exit(void);
--- 65,91 ----
/** 'rtapi_init() sets up the RTAPI. It must be called by any module
! that intends to use the API, before any other RTAPI calls.
! 'modname' can optionally point to a string that identifies
! the module. The string will be truncated at 32 characters.
! If 'modname' is NULL, the system will assign a name.
! On success, returns a positive integer module ID, which is
! used for subsequent calls to rtapi_xxx_new, rtapi_xxx_delete,
! and rtapi_exit. On failure, returns an error code as defined
! above. Call only from within init/cleanup code, not from
! realtime tasks.
*/
! extern int rtapi_init(char *modname);
/** 'rtapi_exit()' shuts down and cleans up the RTAPI. It must be
called prior to exit by any module that called rtapi_init.
! 'module_id' is the ID code returned when that module called
! rtapi_init(). Returns a status code. rtapi_exit() may attempt
! to clean up any tasks and other resources allocated by the
! module, but should not be relied on to replace proper cleanup
! code within the module. Call only from within init/cleanup
! code, not from realtime tasks.
*/
! extern int rtapi_exit(int module_id);
***************
*** 203,220 ****
int value when the task is started.
'prio' is the priority, as determined by one of the priority
! functions above. 'stacksize' is the amount of stack to be used
! for the task - be generous, hardware interrupts may use the same
! stack. 'uses_fp' is a flag that tells the OS whether the task uses
! floating point so it can save the FPU registers on a task switch.
! Failing to save registers when needed causes the dreaded "NAN bug",
! so most tasks should set 'uses_fp' to RTAPI_USES_FP. If a task
definitely does not use floating point, setting 'uses_fp' to
! RTAPI_NO_FP saves a few microseconds per task switch.
! Call only from within init/cleanup code, not from realtime tasks.
*/
#define RTAPI_NO_FP 0
#define RTAPI_USES_FP 1
extern int rtapi_task_new(void (*taskcode) (int),
! int arg, int prio,
unsigned long int stacksize, int uses_fp);
--- 212,231 ----
int value when the task is started.
'prio' is the priority, as determined by one of the priority
! functions above. 'owner' is the module ID of the module that
! is making the call (see rtapi_init). 'stacksize' is the amount
! of stack to be used for the task - be generous, hardware
! interrupts may use the same stack. 'uses_fp' is a flag that
! tells the OS whether the task uses floating point so it can
! save the FPU registers on a task switch. Failing to save
! registers when needed causes the dreaded "NAN bug", so most
! tasks should set 'uses_fp' to RTAPI_USES_FP. If a task
definitely does not use floating point, setting 'uses_fp' to
! RTAPI_NO_FP saves a few microseconds per task switch. Call
! only from within init/cleanup code, not from realtime tasks.
*/
#define RTAPI_NO_FP 0
#define RTAPI_USES_FP 1
extern int rtapi_task_new(void (*taskcode) (int),
! int arg, int prio, int owner,
unsigned long int stacksize, int uses_fp);
***************
*** 299,317 ****
identifies the memory block, and must be non-zero. All modules
wishing to access the same memory must use the same key.
! The block will be at least 'size' bytes, and may be rounded up.
! Allocating many small blocks may be very wasteful. On success,
! it returns a positive integer ID, which is used for all subsequent
! calls dealing with the block. On failure it returns a negative
! error code. Call only from within init/cleanup code, not from
! realtime tasks.
*/
! extern int rtapi_shmem_new(int key, unsigned long int size);
/** 'rtapi_shmem_delete()' frees the shared memory block associated
! with 'shmem_id'. Returns a status code. Call only from within
! init/cleanup code, not from realtime tasks.
*/
! extern int rtapi_shmem_delete(int shmem_id);
/** 'rtapi_shmem_getptr()' sets '*ptr' to point to shared memory block
--- 310,330 ----
identifies the memory block, and must be non-zero. All modules
wishing to access the same memory must use the same key.
! 'module_id' is the ID of the module that is making the call (see
! rtapi_init). The block will be at least 'size' bytes, and may
! be rounded up. Allocating many small blocks may be very wasteful.
! On success, it returns a positive integer ID, which is used for
! all subsequent calls dealing with the block. On failure it
! returns a negative error code. Call only from within init/cleanup
! code, not from realtime tasks.
*/
! extern int rtapi_shmem_new(int key, int module_id, unsigned long int size);
/** 'rtapi_shmem_delete()' frees the shared memory block associated
! with 'shmem_id'. 'module_id' is the ID of the calling module.
! Returns a status code. Call only from within init/cleanup code,
! not from realtime tasks.
*/
! extern int rtapi_shmem_delete(int shmem_id, int module_id);
/** 'rtapi_shmem_getptr()' sets '*ptr' to point to shared memory block
***************
*** 328,346 ****
/** 'rtapi_sem_new()' creates a realtime semaphore. 'key' identifies
identifies the semaphore, and must be non-zero. All modules wishing
! to use the same semaphore must specify the same key. On success, it
! returns a positive integer ID, which is used for all subsequent
! calls dealing with the semaphore. On failure it returns a negative
! error code. Call only from within init/cleanup code, not from
! realtime tasks.
*/
! extern int rtapi_sem_new(int key);
/** 'rtapi_sem_delete()' is the counterpart to 'rtapi_sem_new()'. It
discards the semaphore associated with 'sem_id'. Any tasks blocked
! on 'sem' will resume execution. Returns a status code. Call only
! from within init/cleanup code, not from realtime tasks.
*/
! extern int rtapi_sem_delete(int sem_id);
--- 341,361 ----
/** 'rtapi_sem_new()' creates a realtime semaphore. 'key' identifies
identifies the semaphore, and must be non-zero. All modules wishing
! to use the same semaphore must specify the same key. 'module_id'
! is the ID of the module making the call (see rtapi_init). On
! success, it returns a positive integer semaphore ID, which is used
! for all subsequent calls dealing with the semaphore. On failure
! it returns a negative error code. Call only from within init/cleanup
! code, not from realtime tasks.
*/
! extern int rtapi_sem_new(int key, int module_id);
/** 'rtapi_sem_delete()' is the counterpart to 'rtapi_sem_new()'. It
discards the semaphore associated with 'sem_id'. Any tasks blocked
! on 'sem' will resume execution. 'module_id' is the ID of the calling
! module. Returns a status code. Call only from within init/cleanup
! code, not from realtime tasks.
*/
! extern int rtapi_sem_delete(int sem_id, int module_id);
***************
*** 378,386 ****
/** 'rtapi_fifo_new()' creates a realtime fifo. 'key' identifies the
fifo, all modules wishing to access the same fifo must use the same
! key. 'size' is the depth of the fifo. 'mode' is either 'R' or 'W',
! to request either read or write access to the fifo. On success, it
! returns a positive integer ID, which is used for subsequent calls
! dealing with the fifo. On failure, returns a negative error code.
! Call only from within init/cleanup code, not from realtime tasks.
*/
--- 393,403 ----
/** 'rtapi_fifo_new()' creates a realtime fifo. 'key' identifies the
fifo, all modules wishing to access the same fifo must use the same
! key. 'module_id' is the ID of the module making the call (see
! rtapi_init). 'size' is the depth of the fifo. 'mode' is either
! 'R' or 'W', to request either read or write access to the fifo.
! On success, it returns a positive integer ID, which is used for
! subsequent calls dealing with the fifo. On failure, returns a
! negative error code. Call only from within init/cleanup code,
! not from realtime tasks.
*/
***************
*** 388,400 ****
oops messages on removal. (Does this apply to rtlinux as well ?)
*/
! extern int rtapi_fifo_new(int key, unsigned long int size, char mode);
/** 'rtapi_fifo_delete()' is the counterpart to 'rtapi_fifo_new()'.
! It closes the fifo associated with 'fifo_ID'. 'mode' is the mode
! that was specified when the fifo was created. Returns status code.
! Call only from within init/cleanup code, not from realtime tasks.
*/
! extern int rtapi_fifo_delete(int fifo_id, char mode);
--- 405,418 ----
oops messages on removal. (Does this apply to rtlinux as well ?)
*/
! extern int rtapi_fifo_new(int key, int module_id,
! unsigned long int size, char mode);
/** 'rtapi_fifo_delete()' is the counterpart to 'rtapi_fifo_new()'.
! It closes the fifo associated with 'fifo_ID'. 'module_id' is the
! ID of the calling module. Returns status code. Call only from
! within init/cleanup code, not from realtime tasks.
*/
! extern int rtapi_fifo_delete(int fifo_id, int module_id);
***************
*** 439,448 ****
a hardware interrupt. 'irq' is the interrupt number, and 'handler'
is a pointer to a function taking no arguements and returning void.
! 'handler will be called when the interrupt occurs. Returns a status
code. Note: The simulated RTOS does not support interrupts.
Call only from within init/cleanup code, not from realtime tasks.
*/
! extern int rtapi_assign_interrupt_handler(unsigned int irq,
! void (*handler) (void));
--- 457,467 ----
a hardware interrupt. 'irq' is the interrupt number, and 'handler'
is a pointer to a function taking no arguements and returning void.
! 'handler will be called when the interrupt occurs. 'owner' is the
! ID of the calling module (see rtapi_init). Returns a status
code. Note: The simulated RTOS does not support interrupts.
Call only from within init/cleanup code, not from realtime tasks.
*/
! extern int rtapi_irq_new(unsigned int irq_num, int owner,
! void (*handler) (void));
***************
*** 454,458 ****
init/cleanup code, not from realtime tasks.
*/
! extern int rtapi_free_interrupt_handler(unsigned int irq);
--- 473,477 ----
init/cleanup code, not from realtime tasks.
*/
! extern int rtapi_irq_delete(unsigned int irq_num);
Index: rtapi_common.h
===================================================================
RCS file: /cvsroot/emc/rtapi/src/rtapi/rtapi_common.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** rtapi_common.h 22 Aug 2003 19:48:38 -0000 1.3
--- rtapi_common.h 24 Aug 2003 09:38:25 -0000 1.4
***************
*** 51,57 ****
*/
/* These structs hold data associated with objects like tasks, etc. */
! typedef enum { EMPTY = 0,
PAUSED,
PERIODIC,
--- 51,80 ----
*/
+ /* maximum number of various resources */
+ #define RTAPI_MAX_MODULES 64
+ #define RTAPI_MAX_TASKS 64
+ #define RTAPI_MAX_SHMEMS 32
+ #define RTAPI_MAX_SEMS 64
+ #define RTAPI_MAX_FIFOS 32
+ #define RTAPI_MAX_IRQS 16
+
/* These structs hold data associated with objects like tasks, etc. */
! #define RTAPI_MODULE_NAME_LEN 32
!
! typedef enum {
! NO_MODULE = 0,
! REALTIME,
! USERSPACE
! } mod_type_t;
!
! typedef struct {
! mod_type_t state;
! char name[RTAPI_MODULE_NAME_LEN];
! } module_data;
!
!
! typedef enum {
! EMPTY = 0,
PAUSED,
PERIODIC,
***************
*** 63,66 ****
--- 86,90 ----
task_state_t state; /* task state */
int prio; /* priority */
+ int owner; /* owning module */
void *taskcode; /* task code */
} task_data;
***************
*** 72,85 ****
int ulusers; /* number of user processes using block */
unsigned long size; /* size of shared memory area */
} shmem_data;
typedef struct {
! int users; /* number of modules using the area */
! int key; /* key to shared memory area */
} sem_data;
! typedef enum { UNUSED = 0,
HAS_READER = 1,
HAS_WRITER = 2,
--- 96,112 ----
int ulusers; /* number of user processes using block */
unsigned long size; /* size of shared memory area */
+ char bitmap[(RTAPI_MAX_SHMEMS / 8) + 1]; /* which modules are using block */
} shmem_data;
typedef struct {
! int users; /* number of modules using the semaphore */
! int key; /* key to semaphore */
! char bitmap[(RTAPI_MAX_SEMS / 8) + 1]; /* which modules are using sem */
} sem_data;
! typedef enum {
! UNUSED = 0,
HAS_READER = 1,
HAS_WRITER = 2,
***************
*** 90,93 ****
--- 117,122 ----
fifo_state_t state; /* task state */
int key; /* key to fifo */
+ int reader; /* module ID of reader */
+ int writer; /* module ID of writer */
unsigned long int size; /* size of fifo area */
} fifo_data;
***************
*** 95,108 ****
typedef struct {
int irq_num; /* IRQ number */
} irq_data;
- /* maximum number of various resources */
- #define RTAPI_MAX_TASKS 64
- #define RTAPI_MAX_SHMEMS 32
- #define RTAPI_MAX_SEMS 64
- #define RTAPI_MAX_FIFOS 32
- #define RTAPI_MAX_IRQS 16
-
/* Master RTAPI data structure
There is a single instance of this structure in the machine.
--- 124,132 ----
typedef struct {
int irq_num; /* IRQ number */
+ int owner; /* owning module */
+ void (*handler) (void); /* interrupt handler function */
} irq_data;
/* Master RTAPI data structure
There is a single instance of this structure in the machine.
***************
*** 125,128 ****
--- 149,153 ----
int timer_running; /* state of HW timer */
long int timer_period; /* HW timer period */
+ module_data module_array[RTAPI_MAX_MODULES + 1]; /* data for modules */
task_data task_array[RTAPI_MAX_TASKS + 1]; /* data for tasks */
shmem_data shmem_array[RTAPI_MAX_SHMEMS + 1]; /* data for shared memory */
***************
*** 146,149 ****
--- 171,175 ----
rtapi_data_t *rtapi_data = NULL;
+ module_data *module_array = NULL;
task_data *task_array = NULL;
shmem_data *shmem_array = NULL;
***************
*** 199,203 ****
static void init_rtapi_data(rtapi_data_t * data)
{
! int n;
/* has the block already been initialized? */
--- 225,229 ----
static void init_rtapi_data(rtapi_data_t * data)
{
! int n, m;
/* has the block already been initialized? */
***************
*** 221,227 ****
--- 247,258 ----
data->timer_period = 0;
/* init the arrays */
+ for (n = 0; n <= RTAPI_MAX_MODULES; n++) {
+ data->module_array[n].state = EMPTY;
+ data->module_array[n].name[0] = '\0';
+ }
for (n = 0; n <= RTAPI_MAX_TASKS; n++) {
data->task_array[n].state = EMPTY;
data->task_array[n].prio = 0;
+ data->task_array[n].owner = 0;
data->task_array[n].taskcode = NULL;
}
***************
*** 231,238 ****
--- 262,275 ----
data->shmem_array[n].ulusers = 0;
data->shmem_array[n].size = 0;
+ for (m = 0; m < (RTAPI_MAX_SHMEMS / 8) + 1; m++) {
+ data->shmem_array[n].bitmap[m] = 0;
+ }
}
for (n = 0; n <= RTAPI_MAX_SEMS; n++) {
data->sem_array[n].users = 0;
data->sem_array[n].key = 0;
+ for (m = 0; m < (RTAPI_MAX_SEMS / 8) + 1; m++) {
+ data->sem_array[n].bitmap[m] = 0;
+ }
}
for (n = 0; n <= RTAPI_MAX_FIFOS; n++) {
***************
*** 240,246 ****
--- 277,287 ----
data->fifo_array[n].key = 0;
data->fifo_array[n].size = 0;
+ data->fifo_array[n].reader = 0;
+ data->fifo_array[n].writer = 0;
}
for (n = 0; n <= RTAPI_MAX_IRQS; n++) {
data->irq_array[n].irq_num = 0;
+ data->irq_array[n].owner = 0;
+ data->irq_array[n].handler = NULL;
}
/* done, release the mutex */
Index: rtapi_proc.h
===================================================================
RCS file: /cvsroot/emc/rtapi/src/rtapi/rtapi_proc.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** rtapi_proc.h 22 Aug 2003 19:48:38 -0000 1.3
--- rtapi_proc.h 24 Aug 2003 09:38:25 -0000 1.4
***************
*** 53,57 ****
information, go to www.linuxcnc.org.
*/
- #include "procfs_macros.h"
/* Internal function for the proc_fs system. */
--- 53,56 ----
***************
*** 65,70 ****
--- 64,72 ----
#ifdef CONFIG_PROC_FS
+ #include "procfs_macros.h" /* macros for read functions */
+
static struct proc_dir_entry *rtapi_dir = 0; /* /proc/rtapi directory */
static struct proc_dir_entry *status_file = 0; /* /proc/rtapi/status */
+ static struct proc_dir_entry *modules_file = 0; /* /proc/rtapi/modules */
static struct proc_dir_entry *tasks_file = 0; /* /proc/rtapi/tasks */
static struct proc_dir_entry *shmem_file = 0; /* /proc/rtapi/shmem */
***************
*** 90,97 ****
PROC_PRINT(" RT Modules = %i\n", rtapi_data->rt_module_count);
PROC_PRINT(" UL Modules = %i\n", rtapi_data->ul_module_count);
! PROC_PRINT(" Tasks = %i/%i\n", rtapi_data->task_count, RTAPI_MAX_TASKS);
! PROC_PRINT("Shared memory = %i/%i\n", rtapi_data->shmem_count, RTAPI_MAX_SHMEMS);
! PROC_PRINT(" FIFOs = %i/%i\n", rtapi_data->fifo_count, RTAPI_MAX_FIFOS);
! PROC_PRINT(" Semaphores = %i/%i\n", rtapi_data->sem_count, RTAPI_MAX_SEMS);
PROC_PRINT(" Interrupts = %i\n", rtapi_data->irq_count);
if (rtapi_data->timer_running) {
--- 92,103 ----
PROC_PRINT(" RT Modules = %i\n", rtapi_data->rt_module_count);
PROC_PRINT(" UL Modules = %i\n", rtapi_data->ul_module_count);
! PROC_PRINT(" Tasks = %i/%i\n", rtapi_data->task_count,
! RTAPI_MAX_TASKS);
! PROC_PRINT("Shared memory = %i/%i\n", rtapi_data->shmem_count,
! RTAPI_MAX_SHMEMS);
! PROC_PRINT(" FIFOs = %i/%i\n", rtapi_data->fifo_count,
! RTAPI_MAX_FIFOS);
! PROC_PRINT(" Semaphores = %i/%i\n", rtapi_data->sem_count,
! RTAPI_MAX_SEMS);
PROC_PRINT(" Interrupts = %i\n", rtapi_data->irq_count);
if (rtapi_data->timer_running) {
***************
*** 108,111 ****
--- 114,149 ----
+ static int proc_read_modules(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+ {
+ int n;
+ char *state_str;
+
+ PROC_PRINT_VARS;
+ MOD_INC_USE_COUNT;
+ PROC_PRINT("******* RTAPI MODULES *******\n");
+ PROC_PRINT("ID Type Name\n");
+ for (n = 1; n <= RTAPI_MAX_MODULES; n++) {
+ if (module_array[n].state != NO_MODULE) {
+ switch (module_array[n].state) {
+ case REALTIME:
+ state_str = "RT ";
+ break;
+ case USERSPACE:
+ state_str = "USER";
+ break;
+ default:
+ state_str = "????";
+ break;
+ }
+ PROC_PRINT("%02d %s %s\n", n, state_str, module_array[n].name);
+ }
+ }
+ PROC_PRINT("\n");
+ MOD_DEC_USE_COUNT;
+ PROC_PRINT_DONE;
+ }
+
+
static int proc_read_tasks(char *page, char **start, off_t off,
int count, int *eof, void *data)
***************
*** 117,121 ****
MOD_INC_USE_COUNT;
PROC_PRINT("******** RTAPI TASKS ********\n");
! PROC_PRINT("ID State Code\n");
for (n = 1; n <= RTAPI_MAX_TASKS; n++) {
if (task_array[n].state != EMPTY) {
--- 155,159 ----
MOD_INC_USE_COUNT;
PROC_PRINT("******** RTAPI TASKS ********\n");
! PROC_PRINT("ID Own Prio State Code\n");
for (n = 1; n <= RTAPI_MAX_TASKS; n++) {
if (task_array[n].state != EMPTY) {
***************
*** 137,141 ****
break;
}
! PROC_PRINT("%02d %s %p\n", n, state_str, task_array[n].taskcode);
}
}
--- 175,180 ----
break;
}
! PROC_PRINT("%02d %02d %3d %s %p\n", n, task_array[n].owner,
! task_array[n].prio, state_str, task_array[n].taskcode);
}
}
***************
*** 156,164 ****
PROC_PRINT("ID Users Key Size\n");
PROC_PRINT(" RT/UL \n");
! for ( n = 1 ; n <= RTAPI_MAX_SHMEMS ; n++ ) {
! if ( shmem_array[n].key != 0 ) {
PROC_PRINT("%02d %2d/%-2d %-10d %-10lu\n",
! n, shmem_array[n].rtusers, shmem_array[n].ulusers,
! shmem_array[n].key, shmem_array[n].size);
}
}
--- 195,203 ----
PROC_PRINT("ID Users Key Size\n");
PROC_PRINT(" RT/UL \n");
! for (n = 1; n <= RTAPI_MAX_SHMEMS; n++) {
! if (shmem_array[n].key != 0) {
PROC_PRINT("%02d %2d/%-2d %-10d %-10lu\n",
! n, shmem_array[n].rtusers, shmem_array[n].ulusers,
! shmem_array[n].key, shmem_array[n].size);
}
}
***************
*** 293,296 ****
--- 332,342 ----
status_file->read_proc = proc_read_status;
+ /* create read only file "/proc/rtapi/modules" */
+ modules_file = create_proc_entry("modules", S_IRUGO, rtapi_dir);
+ if (modules_file == NULL) {
+ return -1;
+ }
+ modules_file->read_proc = proc_read_modules;
+
/* create read only file "/proc/rtapi/tasks" */
tasks_file = create_proc_entry("tasks", S_IRUGO, rtapi_dir);
***************
*** 347,350 ****
--- 393,400 ----
status_file = NULL;
}
+ if (modules_file != NULL) {
+ remove_proc_entry("modules", rtapi_dir);
+ modules_file = NULL;
+ }
if (tasks_file != NULL) {
remove_proc_entry("tasks", rtapi_dir);
***************
*** 372,374 ****
#endif /* CONFIG_PROC_FS */
! #endif /* RTAPI_COMMON_H */
--- 422,424 ----
#endif /* CONFIG_PROC_FS */
! #endif /* RTAPI_PROC_H */
Index: sim_rtapi.c
===================================================================
RCS file: /cvsroot/emc/rtapi/src/rtapi/sim_rtapi.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -d -r1.8 -r1.9
*** sim_rtapi.c 11 Aug 2003 04:58:39 -0000 1.8
--- sim_rtapi.c 24 Aug 2003 09:38:25 -0000 1.9
***************
*** 306,310 ****
! int rtapi_shmem_new(int key, unsigned long int size, rtapi_shmem_handle * shmemptr)
{
rtapi_shmem_handle shmem;
--- 306,311 ----
! int rtapi_shmem_new(int key, unsigned long int size,
! rtapi_shmem_handle * shmemptr)
{
rtapi_shmem_handle shmem;
Index: sim_ulapi.c
===================================================================
RCS file: /cvsroot/emc/rtapi/src/rtapi/sim_ulapi.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** sim_ulapi.c 11 Aug 2003 04:58:39 -0000 1.4
--- sim_ulapi.c 24 Aug 2003 09:38:25 -0000 1.5
***************
*** 40,44 ****
! int ulapi_shmem_new(int key, unsigned long int size, ulapi_shmem_handle * shmemptr)
{
ulapi_shmem_handle shmem;
--- 40,45 ----
! int ulapi_shmem_new(int key, unsigned long int size,
! ulapi_shmem_handle * shmemptr)
{
ulapi_shmem_handle shmem;
Index: ulapi.h
===================================================================
RCS file: /cvsroot/emc/rtapi/src/rtapi/ulapi.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -d -r1.9 -r1.10
*** ulapi.h 20 Aug 2003 03:16:21 -0000 1.9
--- ulapi.h 24 Aug 2003 09:38:25 -0000 1.10
***************
*** 66,81 ****
/** 'ulapi_init() sets up the user space interface to the RTAPI.
! It must be called before calling any ulapi functions. Returns
! a status code, as defined above.
*/
! extern int ulapi_init(void);
/** 'ulapi_exit()' shuts down and cleans up the user space interface
! to the RTAPI. It must be called before program exit. Returns a
! status code.
*/
! extern int ulapi_exit(void);
/***********************************************************************
--- 66,92 ----
/** 'ulapi_init() sets up the user space interface to the RTAPI.
! It must be called before calling any ulapi functions.
! 'modname' can optionally point to a string that identifies
! the module. The string will be truncated at 32 characters.
! If 'modname' is NULL, the system will assign a name.
! On success, returns a positive integer module ID, which is
! used for subsequent calls to ulapi_xxx_new, ulapi_xxx_delete,
! and ulapi_exit. On failure, returns a negative error code as
! defined above.
*/
! extern int ulapi_init(char *modname);
/** 'ulapi_exit()' shuts down and cleans up the user space interface
! to the RTAPI. It must be called prior to exit by any module
! that called ulapi_init. 'module_id' is the ID code returned
! when that module called ulapi_init(). ulapi_exit() may attempt
! to clean up any resources allocated by the module, but should
! not be relied on to replace proper cleanup code within the
! module. Returns a status code.
*/
! extern int ulapi_exit(int module_id);
+ extern void ulapi_printall(void);
/***********************************************************************
***************
*** 85,102 ****
/** 'ulapi_shmem_new()' allocates a block of shared memory. 'key'
identifies the memory block, and must be non-zero. All modules
! wishing to access the same memory must use the same key. The
! block will be at least 'size' bytes, and may be rounded up.
! Allocating many small blocks may be very wasteful. On success,
! it returns a positive integer ID, which is used for all subsequent
! calls dealing with the block. On failure, it returns a negative
! error code.
*/
! extern int ulapi_shmem_new(int key, unsigned long int size );
/** 'ulapi_shmem_delete()' frees the shared memory block associated
! with 'shmem_id'. Returns a status code.
*/
! extern int ulapi_shmem_delete(int shmem_id);
--- 96,115 ----
/** 'ulapi_shmem_new()' allocates a block of shared memory. 'key'
identifies the memory block, and must be non-zero. All modules
! wishing to access the same memory must use the same key.
! 'module_id' is the ID of the module that is making the call
! (see ulapi_init). The block will be at least 'size' bytes,
! and may be rounded up. Allocating many small blocks may be very
! wasteful. On success, it returns a positive integer ID, which is
! used for all subsequent calls dealing with the block. On failure,
! it returns a negative error code.
*/
! extern int ulapi_shmem_new(int key, int module_id, unsigned long int size);
/** 'ulapi_shmem_delete()' frees the shared memory block associated
! with 'shmem_id'. 'module_id' is the ID of the calling module.
! Returns a status code.
*/
! extern int ulapi_shmem_delete(int shmem_id, int module_id);
***************
*** 113,130 ****
/** 'ulapi_fifo_new()' opens a fifo for communication with realtime
code. 'key' identifies the fifo, all modules wishing to access the
! same fifo must use the same key. 'size' is the size of the desired
! fifo. 'mode' is either 'R' or 'W', for readable or writeable fifos.
! On success, returns a positive integer fifo ID to be used for all
! subsequent calls dealing with the fifo. On failure, returns a
! negative error code.
*/
! extern int ulapi_fifo_new(int key, unsigned long int size, char mode );
/** 'ulapi_fifo_delete()' is the counterpart to 'rtapi_fifo_new()'.
! It closes the fifo associated with 'fifo_ID'. 'mode' is the mode
! that was specified when the fifo was created. Returns status code.
*/
! extern int ulapi_fifo_delete(int fifo_id, char mode);
--- 126,145 ----
/** 'ulapi_fifo_new()' opens a fifo for communication with realtime
code. 'key' identifies the fifo, all modules wishing to access the
! same fifo must use the same key. 'module_id' is the ID of the
! module making the call (see rtapi_init). 'size' is the size of
! the desired fifo. 'mode' is either 'R' or 'W', for readable or
! writeable fifos. On success, returns a positive integer fifo ID
! to be used for all subsequent calls dealing with the fifo. On
! failure, returns a negative error code.
*/
! extern int ulapi_fifo_new(int key, int module_id,
! unsigned long int size, char mode);
/** 'ulapi_fifo_delete()' is the counterpart to 'rtapi_fifo_new()'.
! It closes the fifo associated with 'fifo_ID'. 'module_id' is
! the ID of the calling module. Returns a status code.
*/
! extern int ulapi_fifo_delete(int fifo_id, int module_id);
|