Wrox Home  
Search P2P Archive for: Go

  Return to Index  

pro_linux_programming thread: reading data from threads


Message #1 by "Serban Udrea" <S.Udrea@g...> on Wed, 14 Mar 2001 14:35:18 -0100
Hi Serban.

Well, my message with attached files didn't get through...
So, I'm resending this sample of locking/unlocking technique.
You shall have some place shared memory to have common structure for locking.
There is source code of locking/unlocking mechanism and part of my header file
I used in my project. 

Please, ask any questions.

Best regards, 
Konstantyn
==============================================================================================================
# ATOMIC.S file
# Low level procedures for locking/unlocking technique.
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#
#    This file contains code for operations that must be performed
#    atomically.
#
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#
#   This gets a unique key value. It is not random. It is just non-zero
#   and unique.
#
#   int get_key(int *key_pointer);
#

WRDBUF = 0x08
INTVAL = 0x0c

.section .text
.global  get_key
.type    get_key,@function

get_key:
	push %ebx
	movl WRDBUF(%esp), %ebx	# Pointer to the previous key
1:	lock
	incl (%ebx)
	jz   1b
	movl (%ebx), %eax
	cmpl (%ebx), %eax
	jnz  1b
	pop %ebx
	ret
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#
#   This adds an input value to the integer pointed to with the
#   input pointer. It returns the result.
#
#   With Intel processors, interrupts are not acknowledged until the
#   instructions following any locked operation and they are not
#   acknowledged until the instructions following stack operations.
#   This allows us to not only perform an atomic operation, but also 
#   to atomically return the result of that operation.
#
#  int atomic_add(int *result, int value);
#
.global atomic_add
.type atomic_add,@function

atomic_add:
	push %ebx
	movl WRDBUF(%esp), %ebx	# Pointer to the result 
	movl INTVAL(%esp), %eax # Value to add
	lock
	addl %eax, (%ebx)       # Add atomically
	pushl (%ebx)		# Result on the stack
	popl  %eax 		# Return the result
	pop  %ebx
	ret

#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#
#   This subtracts an input value from the integer pointed to with the
#   input pointer. We return the result, but the 'C' declaration pretends
#   that we don't so we don't have to cast to void to eliminate warnings.
#
#   Simply change the declaration if you want to use the result.
#
#   int atomic_sub(int *result, int value);
#
.global atomic_sub
.type atomic_sub,@function

atomic_sub:
	push %ebx
	movl WRDBUF(%esp), %ebx	# Pointer to the result 
	movl INTVAL(%esp), %eax # Value to subtract 
	lock
	subl %eax, (%ebx)       # Subtract atomically
	pushl (%ebx)		# Result on the stack
	popl  %eax 		# Return the result
	pop  %ebx
	ret
.end
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
*    LOCKING.C file
 *   This file contains code to lock up to 32 virtual devices. This
 *   code doesn't care what those devices are. It just provides a
 *   single thread for access to a device by a calling procedure.
 *
 *   Any time there is a chance of another process changing the state
 *   of a virtual device, the device should be locked, manipulated,
 *   then unlocked.
 */

#include <stdio.h>
#include <unistd.h>
#include <sched.h>
#include <global.h>

#define MAX_SLEEP 0x800
#define TRIES 10 

extern CC_GBL *cgcd;                        /* Shared memory address     */

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
 *   This locks the virtual device. A process failing to obtain the lock
 *   will give up the CPU until the lock is obtained. To prevent deadlocks,
 *   each task failing to obtain a lock will sleep for different amount
 *   of time.
 *
 *   It is possible for a task to die because of a network hangup with
 *   a lock still held on a device. If this happens, the lock is released
 *   if it is found that the holder of the lock no longer exists.
 */
void lock_dev(int dev)
{
    int key;
    int tries;
    for(;;)
    {
        for(tries = 0; tries < TRIES; tries++)
        {
            key = get_key(&cgcd->key);              /* Get some key value    */
            if(atomic_add(&cgcd->lock[dev].loc, key) == key)
            {
                cgcd->lock[dev].pid = getpid();     /* Identify lock owner   */
                cgcd->lock[dev].key = key;          /* Save for unlock       */
                return;                             /* We own the device     */
            }
            atomic_sub(&cgcd->lock[dev].loc, key);  /* It's busy, try later  */
            usleep(rnd(&cgcd->random) % MAX_SLEEP); /* Give up some CPU time */
        }
        if(!!kill(cgcd->lock[dev].pid, 0))          /* If PID does not exist */
            unlock_dev(dev);
    }
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
 *  This unlocks the virtual device. Note that since the device is locked,
 *  it is safe to change any lock parameters as long as we do it before
 *  we actually unlock the device.
 */
void unlock_dev(int dev)
{
    int key;
    key = cgcd->lock[dev].key;                 /* Get current key   */
    cgcd->lock[dev].key = 0;                   /* Clear key value   */
    cgcd->lock[dev].pid = 0;                   /* Clear owner pid   */
    atomic_sub(&cgcd->lock[dev].loc, key);     /* Now unlock device */
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

/* --------------------------------------------------------------------
*    GLOBAL.H
*    Part of header file
*/
typedef struct {
    pid_t            pid;                  /* Process requested lock    */  
    unsigned long  loc;               /* Loc variable            */
    unsigned long key;               /* Initial key               */ 
} DEVLOCK;
/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
/*
*    This is the main global structure for the CC system.
*    At startup and at run time, all processes and daemons get
*    a pointer to a shared memory with this structure mapped into it.
*/
typedef struct {
    unsigned long    status;                      /* Status or error code   */
    unsigned long    last_stat;                   /* Status or error code   */
    unsigned long    panic;                       /* Bad internal error     */
    unsigned long    last_absvc;                  /* Absolute view cnt val  */
    unsigned long    version;                     /* CC version number      */
    unsigned long    uptime;                      /* CC uptime              */
    unsigned long    can_com_fail;                /* CAN comm. failed       */
    unsigned long    can_com_ok;                  /* CAN comm. failed       */
    unsigned long    err_tot;                     /* Total  errors count    */
    unsigned short   cmd_scan_len;                /* Commanded length TOPO  */
    unsigned short   cmd_spr_len;                 /* Commanded length TOPO  */
    signed   short   cmd_tb_pos;                  /* Commanded table pos    */
    signed   short   topo_end_pos;                /* Commanded end tbl pos  */
    signed   short   spr_end_pos;                 /* Commanded end tbl pos  */
    unsigned short   cmd_tb_spd;                  /* Commanded table speed  */
    unsigned short   err_que_cnt;                 /* Error queue counter    */
    unsigned short   err_got_cnt;                 /* Error read  counter    */
    unsigned short   can_dem_stat;                /* CAN write daemon stat  */
    unsigned short   canr_dem_stat;               /* CAN read  daemon stat  */
    unsigned short   hvpd_dem_stat;               /* CAN system daemon stat */
    unsigned short   gmcd_dem_stat;               /* CAN system daemon stat */
    unsigned short   irs_dem_stat;                /* IRS system daemon stat */
    unsigned short   life_dem_stat;               /*  LIFE daemon stat      */
    unsigned short   ui_dem_stat;                 /*  UI daemon stat        */
    unsigned short   errl_dem_stat;               /*  ERRLOG daemon stat    */
    unsigned short   cmdq_dem_stat;               /*  CMDQUE daemon stat    */
    unsigned short   crn_dem_stat;                /*  Cron daemon stat      */
    unsigned short   img_prs_stat;                /*  Image task status     */
    unsigned short   axial_angle_start;           /*  Start angle for AXIAL */
    unsigned short   cmd_rt_ang;                  /* Commanded stop angle   */
    unsigned short   axl_offs;                    /* Axial sync offset      */
    unsigned short   start_prec;                  /* Start postrecon index  */
    unsigned short   cmd_sh_tim;                  /* Command shot time 0.01s*/
    unsigned char    cmd_rt_spd;                  /* Commanded rotate spd   */
    unsigned char    cmd_tbl_feed;                /* Commanded table feed   */
    unsigned char    cmd_feed_dir;                /* Commanded feed direct  */
    unsigned char    gantry_cmd;                  /* Command to be executed */
    unsigned char    cmd_mA;                      /* Commanded current      */
    unsigned char    cmd_kV;                      /* Commanded voltage      */
    unsigned char    cmd_num_rot;                 /* Commanded number of rot*/
    unsigned char    last_slice_set;              /* Last cmd collim slice  */
    unsigned char    cmd_slice_set;               /* Commanded collim slice */
    signed   char    def_slice_adj;               /* Default slice adjust   */
    signed   char    cmd_coil;                    /* Commanded deflect coil */
    signed   char    cmd_sladj;                   /* Slice adjustment       */
    unsigned char    cmd_misc;                    /* Commanded misc bit ctrl*/
    unsigned char    mode;                        /* Global CC mode         */
    unsigned char    img_mode;                    /* Image mode             */
    unsigned char    ui_lchk;                     /* UI lifecheck flag      */
    unsigned char    ui_up;                       /* UI connected flag      */
    unsigned char    irs_up;                      /* IRS run flag           */
    unsigned char    cc_alive;                    /* Flag for shutdown      */
    unsigned char    motion;                      /* Motion flag            */
    unsigned char    angle;                       /* Angle done flag        */
    unsigned char    cmd_pitch;                   /* Commanded pitch value  */
    unsigned char    can_mem_lock;                /* CAN memory semaphore   */
    unsigned char    emstop;                      /* Emergency stop         */
    unsigned char    drswtch;                     /* Door switch flag       */
    unsigned char    termscan;                    /* Terminate scan         */
    unsigned char    sys_lchk;                    /* System lifecheck flag  */
    unsigned char    err_fl;                      /* Error in queue flag    */
    unsigned char    slices;                      /* Number of slices to mak*/
    unsigned char    remain_imgs;                 /* Number of images remain*/
    unsigned char    xray;                        /* XRAY status            */
    unsigned char    plamps;                      /* Patient lamps flag     */
    unsigned char    lchk_send;                   /* Send lifecheck sequence*/
    unsigned char    sys_lchk_tout;               /* System lifecheck tout  */
    unsigned char    postrecon;                   /* Postrecon              */
    unsigned char    debug_mode;                  /* CC debug mode          */
    unsigned char    shutdown_mode;               /* CC shutdown mode       */
    unsigned char    scan_abort;                  /* Abort all scan process */
    unsigned char    fail_safe;                   /* Failsafe mode          */
    unsigned char    do_fails;                    /* Acivate failsafe flag  */
    unsigned char    gmc_rset;                    /* GMC reset              */
    unsigned char    hvp_rset;                    /* HVPS reset             */
    unsigned char    test_timer;                  /* TEST ONLY!!!!!!!!!!!!  */
    unsigned char    init_things;                 /* Initialize mode flags  */
    unsigned char    unused0;
    unsigned char    unused1;
    unsigned char    unused2;
    pid_t            ftc_pid;                     /* File transfer daemon   */
    pid_t            sav_pid;                     /* IRS second child PID   */
/*  Global Structures that can be acceced from any process */
    CHLD_PID         ch_pid[PROC_NUM];            /* Child PID structure    */
    IRS_GBL          ap;                          /* AP-85 global structure */
    GMC_GBL          gmc;                         /* GMC global structure   */
    HVPS_GBL         hvps;                        /* HVPS global structure  */
    UI_GBL           ui;                          /* UI global structure    */
    NET_INFO         net;                         /* Network information    */
    GMC_CMD          gcmd;                        /* GMC command structure  */
    HVPS_CMD         hcmd;                        /* HVPS command structure */
    READ_BUF         rbuf;                        /* Response buffer        */
    UI_LCHK          uil;                         /* UI LifeCheck struct buf*/
    UI_CMD           uic;                         /* UI Commnad struct buf  */
    UI_LCHK          uil_ack;                     /* Response on the lifech */
    AP85_CMD         apcmd;                       /* AP-85 command str copy */
    SYS_TIMERS       syst;                        /* System timers          */
    REM_QUEUE        _queue[QUEUE_NUM];           /* System queues          */
    REC_GBL          rec;                         /* Reconstruction daemon  */
    TBL_MON          tblm;                        /* Table monitor structure*/
    GNT_MON          gntm;                        /* Gantry monitor struct  */
    XRY_MON          xraym;                       /* XRAY monitor struct    */
    HVP_MON          hvpsm;                       /* HVPS monitor struct    */
    HW_CTRL          hwc;                         /* Hardware enable/disabl */
    PREC_INFO        pinf;                        /* Postreconstruction info*/
    ZMON_CFG         zmc;                         /* Z monitor config       */
    DEVLOCK          lock[DEVICES];               /* Device lock structure  */
} CC_GBL;

===============================================================================================================


On Fri, 16 Mar 2001, Serban Udrea wrote:
> Hello,
> 
> And many thanks to all who did answer my question. Now I am pretty sure
> that I don't need access control for the piece of data I was talking in my
> first message.
> 
> Special thanks go to Konstantin Prokopenko whos' kind offer I gladly
> accept.
> 
> Regards,
> 
> Serban
> 
> 
> 
> -- 
> 
>
#<><><><><><><><><><><><><><><><><
;><><><><><><><><><><><><><><><><>
;<><><><><>#
> # "Human beings, like all other life forms, are parts of an inseparable      #
> # organic whole. Their intelligence, therefore, implies that, the whole too  #
> # is intelligent"                                                            #
>
#<><><><><><><><><><><><><><><><><
;><><><><><><><><><><><><><><><><>
;<><><><><>#
> 
> Serban Udrea
> S.Udrea@g...
> GSI - Plasma Physics Department
> Darmstadt, Germany
> 

  Return to Index