65 of 158
59 For special circumstances, it is possible to specify the task’s stack by giving its address as an integral value. Generally, it will also be advisable to specify the size of the stack since the compiler will be unable to deduce the size. Unless the task stack size is specified or can be deduced, no stack overrun checking can be performed. For native mode ZX devices (e.g. the ZX-24n) the task size must be explicitly specified or it must be determinable by the compiler at compile time, otherwise, the compiler will issue an error message. The syntax for these advanced options is described in the ZBasic System Library Reference manual. Also, see Section 3.27 for additional information on task management. 3.6 Semaphores In computer science a semaphore is a mechanism used to control access to a shared resource, the idea being to prevent more than one actor from attempting to use, modify or update a resource simultaneously. As a physical analogy, consider a long single-lane tunnel on a roadway. A driver waiting to enter at one end would like to be certain that no car enters the tunnel from the opposite end while he is enroute. A semaphore indicating that a vehicle is in the tunnel would, if properly observed, help prevent simultaneous use of the shared resource. Clearly, however, if not all drivers understand the meaning of the semaphore or if a driver ignores the semaphore an accident is likely to occur. So it is with semaphores in a computer program. In a single task system there is no need for semaphores because there are not multiple actors to coordinate. However, in a multitasking system (or a multiprocessor system) because there are multiple actors there is a need to coordinate access to shared resources such as a serial channel, a timer a data structure, etc. Whether or not you need to use a semaphore in your program depends on how it is structured and what resources are shared between tasks. The essential element of a semaphore is known in computer science as an atomic test and set operation. The basic idea is that a method is needed to test a Boolean variable to see if it is already set true and if it is not set then set it to true. The adjective atomic in this case refers to the fact that the testing phase and the setting phase are indivisible. That is, once a task begins the process of testing, no other task is able to begin testing until the first task has completed the test and set. This prevents what is called a race condition. The atomic test and set operation in ZBasic is provided by the System Library routine Semaphore(). To implement a semaphore you must define a Boolean variable and ensure that it is set to False initially. Then, whenever a task wants to use the shared resource it must first call Semaphore() passing the previously defined variable as a parameter. If the semaphore is already set, the function will return False indicating that the resource is busy. If the semaphore is not already set, the function will set it to True and return True indicating that the semaphore has been successfully obtained. Once the task is finished with the resource, it must set the semaphore variable back to False again so that the next user may successfully acquire a semaphore on the resource. The example code below illustrates the sequence. Dim serSem as Boolean serSem = False ' wait until we get the semaphore Do While (Not Semaphore(serSem)) Loop ' now we can use the controlled resources [add code here] ' finished with the resources, release the semaphore serSem = False