Chapter 9: Dynamic Registers

Team-Fly

"What a depressingly stupid machine," said Marvin and trudged away.

Douglas Adams, The Restaurant at the End of the Universe

IN ADDITION TO THE AUTOMATIC, or in exceptional cases global, CLINT objects used up to now, it is sometimes practical to be able to create and purge CLINT variables automatically. To this end we shall create several functions that will enable us to generate, use, clear, and remove a set of CLINT objects, the so-called register bank, as a dynamically allocated data structure, where we take up the sketch presented in [Skal] and work out the details for its use with CLINT objects.

We shall divide the functions into private management functions and public functions; the latter of these will be made available to other external functions for manipulating the registers. However, the FLINT/C functions do not use the registers themselves, so that complete control over the use of the registers can be guaranteed to the user's functions.

The number of registers available should be configurable while the program is running, for which we need a static variable NoofRegs that takes the number of registers, which is predefined in the constant NOOFREGS.

 static USHORT NoofRegs = NOOFREGS; 

Now we define the central data structure for managing the register bank:

 struct clint_registers {   int noofregs;   int created;   clint **reg_l;    /* pointer to vector of CLINT addresses */ }; 

The structure clint_registers contains the variable noofregs, which specifies the number of registers contained in our register bank, and the variable created, which will indicate whether the set of registers is allocated, as well as the pointer reg_l to a vector that takes the start address of the individual registers:

 static struct clint_registers registers = {0, 0, 0}; 

Now come the private management functions allocate_reg_l() to set up the register bank and destroy_reg_l() to clear it. After space for the storage of the addresses of the registers to be allocated has been created and a pointer is then set to the variable registers.reg_l, there follows the allocation of memory for each individual register by a call to malloc() from the C standard library. The fact that CLINT registers are memory units allocated by means of malloc() plays an important role in testing the FLINT/C functions. We shall see in Section 12.2 how this makes possible the examination of any memory errors that may occur.

 static int allocate_reg_l (void) {   USHORT i, j; 

start sidebar

First, memory is allocated for the vector of register addresses.

end sidebar

   if ((registers.reg_l = (clint **) malloc (sizeof(clint *) * NoofRegs)) == NULL)     {       return E_CLINT_MAL;     } 

start sidebar

Now comes the allocation of individual registers. If in the process a call to malloc() ends in an error, all previously allocated registers are cleared and the error code E_CLINT_MAL is returned.

end sidebar

   for (i = 0; i < NoofRegs; i++)     {       if ((registers.reg_l[i] = (clint *) malloc (CLINTMAXBYTE)) == NULL)          {            for (j = 0; j < i; j++)               {                 free (registers.reg_l[j]);               }            return E_CLINT_MAL;    /* error: malloc */          }     }   return E_CLINT_OK; } 

The function destroy_reg_l() is essentially the inverse of the function create_reg_l(): First, the content of the registers is cleared by overwriting them with zeros. Then each individual register is returned by means of free(). Finally, memory pointed to by registers.reg_l is released.

  static void  destroy_reg_l (void)  {    USHORT i;    for (i = 0; i < registers.noofregs; i++)      {         memset (registers.reg_l[i], 0, CLINTMAXBYTE);         free (registers.reg_l[i]);      }    free (registers.reg_l);  } 

Now come the public functions for register management. With the function create_reg_l() we create a set of registers consisting of the number of individual registers determined in NoofRegs. This takes place via a call to the private function allocate_reg_l().

start sidebar

Function:

Allocation of a set of registers of type CLINT

Syntax:

int create_reg_l (void);

Return:

E_CLINT_OK if allocation is ok

E_CLINT_MAL if error with malloc()

end sidebar

 int create_reg_l (void) {   int error = E_CLINT_OK;   if (registers.created == 0)     {       error = allocate_reg_l ();       registers.noofregs = NoofRegs;     }   if (!error)     {       ++registers.created;     }   return error; } 

The structure registers involves the variable registers.created, which is used for counting the number of requested registers to be created. A call to the function free_reg_l() described below results in the set of registers being released only if registers.created has the value 1. Otherwise, registers.created is simply reduced by 1. With the use of this mechanism, called a semaphore, we manage to prevent a set of registers allocated by one function being inadvertently released by another function. On the other hand, every function that requests the set of registers by calling create_reg_l() is responsible for releasing it again with free_reg_l(). Moreover, in general, one cannot assume that the registers contain specific values after a function has been called.

The variable NoofRegs, which determines the number of registers created by create_reg_l(), can be changed by the function set_noofregs_l(). This change, however, remains in effect only until the currently allocated set of registers is released and a new set is created with create_reg_l().

start sidebar

Function:

set number of registers

Syntax:

void set_noofregs_l (unsigned int nregs);

Input:

nregs (number of registers in the register bank)

end sidebar

 void set_noofregs_l (unsigned int nregs) {   NoofRegs = (USHORT)nregs; } 

Now that a set of registers can be allocated, one may ask how individual registers can be accessed. For this it is necessary to select the address field reg_l, dynamically allocated by create_reg_l(), of the above-defined structure clint_reg. This will be accomplished with the help of the function get_reg_l(), introduced below, which returns a pointer to an individual register of the set of registers, provided that the specified ordinal number denotes an allocated register.

start sidebar

Function:

output a pointer to a register

Syntax:

clint * get_reg_l (unsigned int reg);

Input:

reg (register number)

Return:

pointer to the desired register reg, if it is allocated NULL if the register is unallocated

end sidebar

 clint * get_reg_l (unsigned int reg) {   if (!registers.created || (reg >= registers.noofregs))     {       return (clint *) NULL;     }   return registers.reg_l[reg]; } 

Since the set of registers can be changed dynamically with respect to its size and location in memory, it is not recommended that addresses of registers once read be stored for further use. It is much to be preferred that one obtain the register addresses afresh for each use. In the file flint.h are to be found several predefined macros of the form

    #define r0_l get_reg_l(0); 

with the help of which the registers can be invoked, without additional syntactic effort, by their actual current addresses. With the function purge_reg_l(), introduced below, an individual register of the set can be cleared by overwriting it.

start sidebar

Function:

Clear a CLINT register of the register bank by completely overwriting it with zeros

Syntax:

int purge_reg_l (unsigned int reg);

Input:

reg (register number)

Return:

E_CLINT_OK if deletion is ok

E_CLINT_NOR if register is unallocated

end sidebar

 int purge_reg_l (unsigned int reg) {   if (!registers.created || (reg >= registers.noofregs))     {       return E_CLINT_NOR;     }   memset (registers.reg_l[reg], 0, CLINTMAXBYTE);   return E_CLINT_OK; } 

Just as an individual register can be cleared with the function purge_reg_l(), with the function purgeall_reg_l() the complete set of registers can be cleared by overwriting.

start sidebar

Function:

clear all CLINT registers by overwriting with zeros

Syntax:

int purgeall_reg_l (void);

Return:

E_CLINT_OK if deletion is ok

E_CLINT_NOR if registers are not allocated

end sidebar

 int purgeall_reg_l (void) {   USHORT i;   if (registers.created)     {       for (i = 0; i < registers.noofregs; i++)          {            memset (registers.reg_l[i], 0, CLINTMAXBYTE);          }       return E_CLINT_OK;     }   return E_CLINT_NOR; } 

It is good programming style and etiquette to release allocated memory when it is no longer needed. An existing set of registers can be released with the function free_reg_l(). However, as we have explained above, the semaphore registers.created in the structure registers must have been set to 1 before the allocated memory is actually released:

   void   free_reg_l (void)   {     if (registers.created == 1)       {          destroy_reg_l ();       }     if (registers.created)       {          −−registers.created;       }   } 

We now present three functions that create, clear, and again free individual CLINT registers, in analogy to the management of the complete set of registers.

start sidebar

Function:

allocation of a register of type CLINT

Syntax:

clint * create_l (void);

Return:

pointer to allocated registers, if allocation ok NULL if error with malloc()

end sidebar

 clint * create_l (void) {   return (clint *) malloc (CLINTMAXBYTE); } 

It is important to treat the pointer returned by create_l() in such a way that it does not "become lost," since otherwise, it is impossible to access the created registers. The sequence

   clint * do_not_overwrite_l;   clint * lost_l;   /* ... */   do_not_overwrite _l = create_l();   /* ... */   do_not_overwrite _l = lost_l; 

allocates a register and stores its address in a variable with the suggestive name do_not_overwrite_l. If this variable contains the only reference to the register, then after the last instruction,

   do_not_overwrite _l = lost_l; 

the register is lost, which is a typical error in the jungle of pointer management.

A register can, like any other CLINT variable, be cleared with the function purge_l() that follows, whereby the memory reserved for the specified register is overwritten with zeros and thereby cleared.

start sidebar

Function:

clear a CLINT object by completely overwriting with zeros

Syntax:

void purge_l (CLINT n_l);

Input:

n_l (CLINT object)

end sidebar

  void  purge_l (CLINT n_l)  {    if (NULL != n_l)      {         memset (n_l, 0, CLINTMAXBYTE);      }  } 

The following function additionally releases the memory allocated for the specified register after it has been cleared. Afterwards, the register can no longer be accessed.

start sidebar

Function:

clear and release a CLINT register

Syntax:

void free_l (CLINT reg_l);

Input:

reg_l (pointer to a CLINT register)

end sidebar

  void  free_l (CLINT reg_l)  {    if (NULL != reg_l)      {        memset (reg_l, 0, CLINTMAXBYTE);        free (n_l);      }  } 


Team-Fly


Cryptography in C and C++
Cryptography in C and C++
ISBN: 189311595X
EAN: 2147483647
Year: 2001
Pages: 127

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net