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
>