long signal_sem(long semnum)


[説明]

-

semnumで示されたセマフォを解放します。

-

解放できた場合は1、解放できなかった場合は0を返してください。

-

標準ライブラリ構築ツールでreentオプションを指定して作成した標準ライブラリを使用する場合に、本関数は必要になります。

[リターン値]

正常: 1

異常: 0

[引数]

semnum セマフォID

(3)

低水準インタフェースルーチンコーディング例

/******************************************************************************/
/*                                        lowsrc.c:                           */
/*----------------------------------------------------------------------------*/
/*      RXファミリ  シミュレータ・デバッガ  インタフェースルーチン                    */
/*              - 標準入出力(stdin,stdout,stderr)だけをサポートしています -        */
/******************************************************************************/
#include <string.h>
 
/*  ファイル番号  */
#define STDIN  0                         /*  標準入力(コンソール)*/
#define STDOUT 1                         /*  標準出力(コンソール)*/
#define STDERR 2                         /*  標準エラー出力 (コンソール)*/
 
#define FLMIN 0                          /*  最小のファイル番号*/
#define FLMAX 3                          /*  ファイル数の最大値*/
 
/*  ファイルのフラグ  */
#define O_RDONLY 0x0001                  /*  読み込み専用*/
#define O_WRONLY 0x0002                  /*  書き出し専用*/
#define O_RDWR 0x0004                    /*  読み書き両用*/
 
/*  特殊文字コード  */
#define CR 0x0d                          /*  復帰*/
#define LF 0x0a                          /*  改行*/
 
/*  sbrkで管理する領域サイズ  */
#define HEAPSIZE 1024
 
/******************************************************************************/
/*                                     参照関数の宣言:                          */
/*     シミュレータ・デバッガでコンソールへの文字入出力を行うアセンブリプログラムの参照    */
/******************************************************************************/
extern void charput(char);               /*  一文字入力処理*/
extern char charget(void);               /*  一文字出力処理*/
 
/******************************************************************************/
/*                                     静的変数の定義:                          */
/*                    低水準インタフェースルーチンで使用する静的変数の定義             */
/******************************************************************************/
char flmod[FLMAX];                       /*  オープンしたファイルのモード設定場所  */
 
union HEAP_TYPE{
    long dummy;                          /*  4バイトアライメントにするためのダミー*/
    char heap[HEAPSIZE];                 /*  sbrkで管理する領域の宣言*/
};
 
static union HEAP_TYPE heap_area;
 
static char *brk=(char*)&heap_area;      /*  sbrkで割り付けた領域の最終アドレス  */
/******************************************************************************/
/*                                 open:ファイルのオープン                       */
/*                              リターン値:ファイル番号(成功)                    */
/*                                        -1         (失敗)                   */
/******************************************************************************/
long open(const char *name,                        /*  ファイル名*/
           long mode,                              /*  ファイルのモード*/
           long flg)                               /*  処理の指定(未使用)*/
{
    /*  ファイル名に従ってモードをチェックし、ファイル番号を返す  */
 
    if (strcmp(name,"stdin")==0) {                 /*  標準入力ファイル  */
        if ((mode&O_RDONLY)==0) {
            return (-1);
        }
        flmod[STDIN]=mode;
        return (STDIN);
    }
 
    else if (strcmp(name,"stdout")==0) {           /*  標準出力ファイル  */
        if ((mode&O_WRONLY)==0) {
            return (-1);
        }
        flmod[STDOUT]=mode;
        return (STDOUT);
    }
 
    else if (strcmp(name,"stderr")==0){            /* 標準エラー出力ファイル  */
        if ((mode&O_WRONLY)==0) {
            return (-1);
        }
        flmod[STDERR]=mode;
        return (STDERR);
    }
 
    else {
        return (-1);                               /* エラー  */
    }
}
 
/******************************************************************************/
/*                                close:ファイルのクローズ                       */
/*                             リターン値:0           (成功)                   */
/*                                      -1           (失敗)                   */
/******************************************************************************/
long close(long fileno)                            /*  ファイル番号  */
{
    if (fileno<FLMIN || FLMAX<fileno) {            /*  ファイル番号の範囲チェック  */
        return -1;
    }
 
    flmod[fileno]=0;                               /*  ファイルのモードリセット  */
 
    return 0;
}
/******************************************************************************/
/*                                  read:データの読み込み                       */
/*                         リターン値:実際に読み込んだ文字数(成功)                */
/*                                   -1                 (失敗)                */
/******************************************************************************/
long read(long fileno,                      /*  ファイル番号           */
         unsigned char *buf,                /*  転送先バッファアドレス   */
         long  count)                       /*  読み込み文字数          */
{
    unsigned long i;
 
    /*  ファイル名に従ってモードをチェックし、一文字づつ入力してバッファに格納  */
 
    if (flmod[fileno]&O_RDONLY || flmod[fileno]&O_RDWR) {
        for (i=count;i>0;i--) {
            *buf=charget();
            if (*buf==CR) {                 /*  改行文字の置き換え  */
                *buf=LF;
            }
        buf++;
        }
        return count;
    }
 
    else {
        return -1;
    }
}
 
/******************************************************************************/
/*                                  write:データの書き出し                      */
/*                         リターン値:実際に書き出した文字数(成功)                */
/*                                   -1                 (失敗)                */
/******************************************************************************/
long write(long fileno,                     /*  ファイル番号  */
          const unsigned char *buf,         /*  転送元バッファアドレス  */
          long count)                       /*  書き出し文字数  */
{
    unsigned long i;
    unsigned char c;
 
    /*  ファイル名に従ってモードをチェックし、一文字づつ出力  */
 
    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:ファイルの読み込み/書き出し位置の設定               */
/*          リターン値:読み込み/書き出し位置のファイル先頭からのオフセット  (成功)    */
/*                    -1                                            (失敗)    */
/*                   (コンソール入出力では、lseekはサポートしていません)            */
/******************************************************************************/
long lseek(long fileno,                    /*  ファイル番号           */
           long offset,                    /*  読み込み/書き出し位置   */
           long  base)                     /*  オフセットの起点        */
{
    return -1;
}
 
/******************************************************************************/
/*                                sbrk:メモリ領域の割り付け                      */
/*                      リターン値:割り付けた領域の先頭アドレス  (成功)             */
/*                                -1                       (失敗)             */
/******************************************************************************/
char *sbrk(size_t size)                    /*  割り付ける領域のサイズ  */
{
    char *p;
 
    /*  空き領域のチェック  */
 
    if (brk+size>heap_area.heap+HEAPSIZE) {
        return (char *)-1;
    }
 
    p=brk;                                 /* 領域の割り付け       */
    brk+=size;                             /* 最終アドレスの更新    */
    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)

リエントラントライブラリ用低水準インタフェースルーチン例

リエントラントライブラリ用低水準インタフェース例を示します。ライブラリジェネレータでreentオプションを指定して作成したライブラリを使用する場合に必要になります。

wait_sem関数、signal_sem関数でセマフォの確保に失敗した場合、errnoに以下を設定し、ライブラリ関数からリターンします。

表 8.4

リエントラントライブラリがerrnoに設定するエラー番号

関数名

エラー番号(マクロ名)

意味

wait_sem

EMALRESM

malloc用セマフォ資源確保に失敗しました

ETOKRESM

strtok用セマフォ資源確保に失敗しました

EFLSRESM

_Files用セマフォ資源確保に失敗しました

EMBLNRESM

mbrlen用セマフォ資源確保に失敗しました

signal_sem

EMALFRSM

malloc用セマフォ資源解放に失敗しました

ETOKFRSM

strtok用セマフォ資源解放に失敗しました

EFLSFRSM

_Files用セマフォ資源解放に失敗しました

EMBLNFRSM

mbrlen用セマフォ資源解放に失敗しました

割り込みに関しては、セマフォ確保後により優先度の高い割り込みが発生し、セマフォ確保を行うとデッドロックが発生するため、リソースを共有するような処理が割り込みでネストしないようにしてください。

 

#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);
}