long signal_sem (long semnum)


[Description]

-

Releases the semaphore specified by semnum.

-

When the semaphore has been released normally, 1 must be returned. Otherwise, 0 must be returned.

-

This routine is necessary when using a standard library, which was created by the standard library generator with the reent option specified.

[Return value]

Normal: 1

Error: 0

[Parameters]

semnum Semaphore ID

(3)

Example of Coding Low-Level Interface Routines

/******************************************************************************/
/*                                   lowsrc.c:                                */
/*----------------------------------------------------------------------------*/
/*               RX Family Simulator Debugger Interface Routine               */
/*       - Supports only the standard input/output(stdin,stdout,stderr) -     */
/******************************************************************************/
#include <string.h>
 
/* File Numbers */
#define STDIN  0                    /* Standard Input (Console) */
#define STDOUT 1                    /* Standard Output (Console) */
#define STDERR 2                    /* Standard Error Output (Console) */
 
#define FLMIN 0                     /* Minimum value of the File Number */
#define FLMAX 3                     /* Maximum value of the Number of Files */
 
/* File Flags */
#define O_RDONLY 0x0001             /* Read Only */
#define O_WRONLY 0x0002             /* Write Only */
#define O_RDWR 0x0004               /* Read and Write */
 
/* Special Character Codes */
#define CR 0x0d                     /* Carriage Return */
#define LF 0x0a                     /* Line Feed */
 
/* Heap Size of the sbrk */
#define HEAPSIZE 1024
 
/******************************************************************************/
/*                        Declaration of Using Functions                      */
/*         - Outputs and Inputs to a Console on a Simulator Debugger -        */
/******************************************************************************/
extern void charput(char);               /* Inputs a Byte */
extern char charget(void);               /* Outputs a Byte */
 
/******************************************************************************/
/*                        Definition of Static Variables                      */
/*                  - Used by the Low-Level Interface Routine -               */
/******************************************************************************/
char flmod[FLMAX];                       /* Open File Modes */
 
union HEAP_TYPE{
    long dummy;                          /* (Dummy: for 4-bytes alignment) */
    char heap[HEAPSIZE];                 /* Heap Area of the sbrk */
};
 
static union HEAP_TYPE heap_area;
 
static char *brk=(char*)&heap_area;      /* Latest Address of sbrk Assigned */
 

 

/******************************************************************************/
/*                             open --- Open A File                           */
/*                       Return Value: File Number (Success)                  */
/*                                     -1          (Fail)                     */
/******************************************************************************/
long open(const char *name,                        /* File Name */
           long mode,                              /* File Open Mode */
           long flg)                               /* Open Flag (Not Used) */
{
    /* Checks mode of the file, and Returns file number */
 
    if (strcmp(name,"stdin")==0) {            /* Standard Input File */
        if ((mode&O_RDONLY)==0) {
            return (-1);
        }
        flmod[STDIN]=mode;
        return (STDIN);
    }
 
    else if (strcmp(name,"stdout")==0) {      /* Standard Output File */
        if ((mode&O_WRONLY)==0) {
            return (-1);
        }
        flmod[STDOUT]=mode;
        return (STDOUT);
    }
 
    else if (strcmp(name,"stderr")==0){       /* Standard Error Output File */
        if ((mode&O_WRONLY)==0) {
            return (-1);
        }
        flmod[STDERR]=mode;
        return (STDERR);
    }
 
    else {
        return (-1);                          /* Error */
    }
}
 
/******************************************************************************/
/*                             close --- Close A File                         */
/*                           Return Value: 0    (Success)                     */
/*                                        -1    (Fail)                        */
/******************************************************************************/
long close(long fileno)                       /* File Number */
{
    if (fileno<FLMIN || FLMAX<fileno) {       /* Checks the File Number */
        return -1;
    }
 
    flmod[fileno]=0;                          /* Resets the File Mode */
 
    return 0;
}
 
 
/******************************************************************************/
/*                             read --- Input Data                            */
/*                    Return Value: Bytes Number of Read  (Success)           */
/*                                  -1                    (Fail)              */
/******************************************************************************/
long read(long fileno,                      /* File Number */
         unsigned char *buf,                /* Write Buffer Address */
         long  count)                       /* Bytes Number of Read */
{
    unsigned long i;
 
    /*  Checks mode of the file, and Sets the Write Buffer each bytes */
 
    if (flmod[fileno]&O_RDONLY || flmod[fileno]&O_RDWR) {
        for (i=count;i>0;i--) {
            *buf=charget();
            if (*buf==CR) {                 /* Replaces CR into LF */
                *buf=LF;
            }
        buf++;
        }
        return count;
    }
 
    else {
        return -1;
    }
}
 
/******************************************************************************/
/*                            write --- Output Data                           */
/*                    Return Value: Bytes Number of Write (Success)           */
/*                                  -1                    (Fail)              */
/******************************************************************************/
long write(long fileno,                     /* File Number */
          const unsigned char *buf,         /* Read Buffer Address */
          long count)                       /* Bytes Number of Write */
{
    unsigned long i;
    unsigned char c;
 
    /*  Checks mode of the file, and Output from the Rrite Buffer each bytes */
 
    if (flmod[fileno]&O_WRONLY || flmod[fileno]&O_RDWR) {
        for (i=count; i>0; i--) {
            c=*buf++;
            charput(c);
        }
        return count;
    }
 
    else {
        return -1;
    }
}
 
 
/******************************************************************************/
/*                lseek --- Sets Position of Reading and Writing              */
/*              Return Value: Offset of the File Position (Success)           */
/*                            -1                          (Fail)              */
/*              (lseek doesn't support Console Input/Output)                  */
/******************************************************************************/
long lseek(long fileno,                    /* File Number */
           long offset,                    /* Position of Reading and Writing */
           long  base)                     /* Start of Offset */
{
    return -1;
}
 
/******************************************************************************/
/*                    sbrk --- Allocate Heap Memory                           */
/*              Return Value: Top address of Allocated Area (Success)         */
/*                            -1                            (Fail)            */
/******************************************************************************/
char *sbrk(size_t size)                    /* Allcation Memory Size */
{
    char *p;
 
    /* Checks Free Area */
 
    if (brk+size>heap_area.heap+HEAPSIZE) {
        return (char *)-1;
    }
 
    p=brk;                                 /* Allocate an Area */
    brk+=size;                             /* Updates the Latest Address */
    return p;
}
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;                          lowlvl.src                                 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;  RX Family Simulator/Debugger Interface Routine                     ;
;             - Inputs and outputs one character -                    ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
         .GLB    _charput
         .GLB    _charget
 
SIM_IO   .EQU 0h
 
         .SECTION   P,CODE
;-----------------------------------------------------------------------
;  _charput:
;-----------------------------------------------------------------------
_charput:
         MOV.L      #IO_BUF,R2
         MOV.B      R1,[R2]
         MOV.L      #1220000h,R1
         MOV.L      #PARM,R3
         MOV.L      R2,[R3]
         MOV.L      R3,R2
         MOV.L      #SIM_IO,R3
         JSR        R3
         RTS
 
;-----------------------------------------------------------------------
;  _charget:
;-----------------------------------------------------------------------
_charget:
        MOV.L       #1210000h,R1
        MOV.L       #IO_BUF,R2
        MOV.L       #PARM,R3
        MOV.L       R2,[R3]
        MOV.L       R3,R2
        MOV.L       #SIM_IO,R3
        JSR         R3
        MOV.L       #IO_BUF,R2
        MOVU.B      [R2],R1
        RTS
 
;-----------------------------------------------------------------------
;  I/O Buffer
;-----------------------------------------------------------------------
         .SECTION  B,DATA,ALIGN=4
PARM:    .BLKL     1
         .SECTION  B_1,DATA
IO_BUF:  .BLKB     1
         .END

 

(4)

Example of Low-Level Interface Routine for Reentrant Library

The following shows an example of low-level interface routines for a reentrant library. These routines are necessary when using a library, which was created by the library generator with the reent option specified.

When failing to allocate semaphores with the wait_sem function or signal_sem function, set errno as follows to return from the library function.

 

Table 8.4

Error number list of the reentrant library sets to errno variable

Function Name

errno

Description

wait_sem

EMALRESM

Failed to allocate semaphore resources for malloc.

ETOKRESM

Failed to allocate semaphore resources for strtok.

EFLSRESM

Failed to allocate semaphore resources for _Files.

EMBLNRESM

Failed to allocate semaphore resources for mbrlen.

signal_sem

EMALFRSM

Failed to release semaphore resources for malloc.

ETOKFRSM

Failed to release semaphore resources for strtok.

EFLSFRSM

Failed to release semaphore resources for _Files.

EMBLNFRSM

Failed to release semaphore resources for mbrlen.

 

When an interrupt with a priority level higher than the current level is generated after semaphores have been defined, dead locks will occur if semaphores are defined again. Therefore, be careful for processes that share resources because they might be nested by interrupts.

 

#define MALLOC_SEM   1  /* Semaphore No. for malloc */
#define STRTOK_SEM   2  /* Semaphore No. for strtok */
#define FILE_TBL_SEM 3  /* Semaphore No. for fopen  */
#define MBRLEN_SEM   4  /* Semaphore No. for mbrlen */
#define FPSWREG_SEM  5  /* Semaphore No. for FPSW register */
#define FILES_SEM    6  /* Semaphore No. for _Files */
#define SEMSIZE     26  /* FILES_SEM + _nfiles (assumed _nfiles=20) */
 
#define TRUE 1
#define FALSE 0
#define OK 1
#define NG 0
extern long *errno_addr(void);
extern long wait_sem(long);
extern long signal_sem(long);
static long sem_errno;
static int force_fail_signal_sem = FALSE;
static int semaphore[SEMSIZE];
 
/******************************************************************************/
/*                  errno_addr: Acquisition of errno address                  */
/*                        Return value: errno address                         */
/******************************************************************************/
long *errno_addr(void)
{
    /* Return the errno address of the current task */
    return (&sem_errno);
}
 
/******************************************************************************/
/*           wait_sem: Defines the specified numbers of semaphores            */
/*                       Return value: OK(=1) (Normal)                        */
/*                                     NG(=0) (Error)                         */
/******************************************************************************/
long wait_sem(long semnum) /* Semaphore ID */
{
    if((0 < semnum) && (semnum < SEMSIZE)) {
        if(semaphore[semnum] == FALSE) {
            semaphore[semnum] = TRUE;
            return(OK);
        }
    }
    return(NG);
}
 
/******************************************************************************/
/*          signal_sem: Releases the specified numbers of semaphores          */
/*                       Return value: OK(=1) (Normal)                        */
/*                                     NG(=0) (Error)                         */
/******************************************************************************/
long signal_sem(long semnum) /* Semaphore ID */
{
    if(!force_fail_signal_sem) {
        if((0 <= semnum) && (semnum < SEMSIZE)) {
            if( semaphore[semnum] == TRUE ) {
                semaphore[semnum] = FALSE;
                return(OK);
            }
        }
    }
    return(NG);
}