This is an assignment and I have been asked to implement a Semaphore in Ada as the description below.
However I have implemented the Semaphore.adb and called this Semaphore in the producerconsumer_sem.adb which I created.
I get some output which is the following.
I'm not sure if my initialization of semaphore is correct S: CountingSemaphore(1,1);.
I don't know where I call the S.wait and S.Signal now i randomly called the S.wait before Producer put item in the buffer X := I; and the S.Signal after the X := I;.
Is this the correct way?
Producer-Consumer Problem
The program producerconsumer.adb implements a non-reliable implemen-
tation of the producer-consumer problem, where data is likely be lost. In
the following, you will use three different communication mechanisms to
achieve a reliable implementation of the producer-consumer problem.
Semaphore
The Ada language does not directly provide library functions for a semaphore.
However, semaphores can be implemented by means of a protected object. Create a package specification Semaphore in the file Semaphores.ads
and the corresponding package body in the file Semaphores.adb that
implements a counting semaphore. Skeletons for the package are available on the course page.
Use the semaphore package for a reliable implementation of the producer-
consumer problem. Modify the file producerconsumer.adb and save the
final code as producerconsumer_sem.adb. In order to use the semaphore
package it shall be installed in the same directory as producerconsumer_sem.adb.
It can then be accessed by
with Semaphores;
use Semaphores;
The Output:
OutPut:
1
1
1
2
2
3
4
4
5
6
6
7
7
8
9
9
9
10
11
11
11
12
12
13
13
13
14
15
15
16
16
17
18
18
18
19
20
20
21
21
22
22
23
24
24
24
24
25
25
26
27
27
28
29
29
30
30
31
31
32
32
33
33
33
34
35
35
35
36
36
37
37
37
38
38
38
39
40
40
40
The package
package Semaphores is
protected type CountingSemaphore(Max: Natural; Initial: Natural) is
entry Wait;
entry Signal;
private
Count : Natural := Initial;
MaxCount : Natural := Max;
end CountingSemaphore;
end Semaphores;
The Semaphore I implemented semaphores.adb.
package body Semaphores is
protected body CountingSemaphore is
entry Wait when Count > 0 is
begin
Count := Count - 1;
end Wait;
entry Signal when Count < MaxCount is
begin
Count := Count + 1;
end Signal;
end CountingSemaphore;
end Semaphores;
The producerconsumer_sem.adb
with Ada.Text_IO;
use Ada.Text_IO;
with Ada.Real_Time;
use Ada.Real_Time;
with Ada.Numerics.Discrete_Random;
with Semaphores;
use Semaphores;
procedure ProducerConsumer_sem is
X : Integer; -- Shared Variable
N : constant Integer := 40; -- Number of produced and comsumed variables
S: CountingSemaphore(1,1);
--S1: CountingSemaphore(1,1);
pragma Volatile(X); -- For a volatile object all reads and updates of
-- the object as a whole are performed directly
-- to memory (Ada Reference Manual, C.6)
--Random Delays
subtype Delay_Interval is Integer range 50..250;
package Random_Delay is new Ada.Numerics.Discrete_Random
(Delay_Interval);
use Random_Delay;
G : Generator;
task Producer;
task Consumer;
task body Producer is
Next : Time;
begin
Next := Clock;
for I in 1..N loop
-- Write to X
S.Wait;
X := I;
S.Signal;
--Next 'Release' in 50..250ms
Next := Next + Milliseconds(Random(G));
Put_Line(Integer'Image(X));
delay until Next;
end loop;
end;
task body Consumer is
Next : Time;
begin
Next := Clock;
for I in 1..N loop
-- Read from X
S.Wait;
Put_Line(Integer'Image(X));
S.Signal;
Next := Next + Milliseconds(Random(G));
delay until Next;
end loop;
end;
begin -- main task
null;
end ProducerConsumer_sem;
On macOS, with FSF GCC 7.1.0 and GNAT GPL 2017, I changed your Put_Lines to Puts and got pretty-much the answer you state in the question.
The question says to create Semaphore.ads, .adb. This will work on Windows, and may work on macOS, but won’t work on Linux, because of GNAT’s file naming convention (see the end of this; it’s a good idea to get into the habit of using lower-case file names).
If you want to ensure that only one task has access to X at a time, I don’t think there’s much wrong with your Wait, Signal calls, though when I put a delay 0.1 at the beginning of Producer, the first value output was 151619216 (because X isn’t initialized). However! if the point is to communicate one update to X at a time (as implied by the names producer/consumer), you should
initialize the semaphore with a count of 0 (and a max of 1). This makes it a binary semaphore.
in Consumer, Wait only (i.e. remove the Signal)
in Producer, Signal only (i.e. remove the Wait). Also, remove the Put to avoid confusion!
Related
input array: Ram = {D D D D D 3 3 3 3 7 7 7 9 9 8 8};
I am expecting the output as below:
Count = {0 0 0 4 0 0 0 3 2 2 0 0 0 5 0 0};
That is to count the number of occurances, like there are five D's , four 3's , three 7's, two 9's and two 8's so that Count array has 5 in Dth index, 4 in 3rd index, 3 in 7th index and so on.
my code is as below:
architecture behav of Bitcount is
signal cnt: count_type := (others=> (others=>'0'));
use ieee.numeric_std.all;
begin
Countproc:process(clk)
begin
if (clk'event and clk='1' ) then
if Enable='1' then
if (Read_bit='1') then
for k in 0 to 15 loop
for i in 0 to 15 loop
if ( Ram(k) = std_logic_vector(to_unsigned(i, 4)) )then
cnt(i) <= cnt(i) + "01";
end if;
end loop;
end loop;
end if;
end if;
Count <= cnt;
end if;
end process Countproc;
end behav;
but its not working as my expectation . pls help
Your problem is that cnt is a signal. It needs to be a variable.
The lines of code within a process are executed sequentially. Whenever a line of code containing a signal assignment (<=) is executed, an event is put on the event queue to drive the target signal (cnt in this case) on the next delta cycle (assuming there is some change to the target signal as a result). The event queue is the simulator's "to do" list; a delta cycle is one iteration of the simulator; the next iteration will occur once all the processes that are executing in the current iteration suspend.
If, during any execution of a process, another signal assignment to the same target signal is encountered, then (usually*) any other events on the event queue relating to that signal are deleted. So, in your example, every time this line is encountered (which it will be 16*16=256 times):
cnt(i) <= cnt(i) + "01";
Instead of incrementing cnt(i) (which is what I assume you are expecting to happen), all previous events relating to cnt(i) are deleted and replaced with a new event to drive cnt(i) with the value it had before the process started executing plus one. The signal cnt(i) does not get its new value until the process completes executed (and all other processes too).
Variables do not exhibit this behaviour; variables behave just like variables do in any software language. When a line of code is encountered with a variable assignment (:=), the variable is updated immediately and so its value is immediately available for further calculations.
So, how about changing cnt to a variable:
architecture behav of Bitcount is
use ieee.numeric_std.all;
begin
Countproc:process(clk)
variable cnt : count_type;
begin
if (clk'event and clk='1' ) then
if Enable='1' then
if (Read_bit='1') then
cnt := (others=> (others=>'0'));
for k in 0 to 15 loop
for i in 0 to 15 loop
if ( Ram(k) = std_logic_vector(to_unsigned(i, 4)) )then
cnt (i) := cnt (i) + "01";
end if;
end loop;
end loop;
Count <= cnt;
end if;
end if;
end if;
end process Countproc;
end behav;
I can't be sure this will work, because you haven't provided an MCVE, so I haven't tested it. But you original solution will not work for the reason I have given.
--
* this is nearly always true, because of the way that VHDL models delays as inertial delays and it is certainly true in this example. But strictly it's not always true.
I created a simple model in Spin in which two processes S send messages to another process R. Process R then sends responses to both processes. I would like to define the property "if process x sends a message, then process y eventually receives it", as shown below. The problem is that although the simulation is working as expected, verification is not. The property I defined at line 9 is always passing without errors although I injected a fault at line 17 that should make verification fail. Am I missing something here?
1 byte r1PId;
2 byte s1PId;
3 byte s2PId;
4
5 byte nextM = 1;
6
7 chan toS[2] = [2] of {byte};
8
9 ltl p1 {[] ((s[s1PId]:m > 0) -> <>(s[s1PId]:m == r:m))}
10
11 proctype r(byte id; chan stoR)
12 {
13 do
14 :: true
15 byte c; byte m; byte m2;
16 stoR?c, m2;
17 m = 67; //should be m = m2
18
19 byte response = 50;
20
21 toS[c]!response;
22 od
23 }
24
25 proctype s(byte id; chan rtoS; chan stoR)
26 {
27 byte m;
28 atomic
29 {
30 m = nextM;
31 nextM = nextM+1;
32 }
33 stoR!id, m;
34 byte response;
35 rtoS?response;
36 }
37
38 init{
39 chan toR = [10] of {byte, byte};
40 r1PId = run r(10, toR);
41 s1PId = run s(0, toS[0], toR);
42 s2PId = run s(1, toS[1], toR);
43 }
There seems to be a scope problem. When the process s terminates, its local variables will be out of scope. In that case, the reference s[s1PId]:m will be 0.
On the other hand, in the process r, the variable m is declared inside a block. It is initialized to 0 every time before stoR?c, m2.
As a result, the reference r:m will always be 0 after receiving messages twice.
So, <>(s[s1PId]:m == r:m) will always be true.
To quick fix this, you can either (i) move the declaration byte m in r outside the loop; or (ii) add an infinite loop in s to prevent its termination.
I am trying to get used to iSpin/Promela. I am using:
Spin Version 6.4.3 -- 16 December 2014,
iSpin Version 1.1.4 -- 27 November 2014,
TclTk Version 8.6/8.6,
Windows 8.1.
Here is an example where I try to use LTL. The verification of the LTL property should produce an error if the two steps in the for loop are non-atomic:
1 #define ten ((n !=10) && (finished == 2))
2
3 int n = 0;
4 int finished = 0;
5 active [2] proctype P() {
6 //assert(_pid == 0 || _pid == 1);
7
8 int t = 0;
9 byte j;
10 for (j : 1 .. 5) {
11 atomic {
12 t = n;
13 n = t+1;
14 }
15 }
16 finished = finished+1;
17 }
18
19 ltl alwaysten {[] ! ten }
In the verification tap I just want to test the LTL property, so I disable all safety properties and activate "use claim". The claim name is "alwaysten".
But it seems that the LTL property is just evaluated if I activate "assertion violations". Why? A collegue is using iSpin v1.1.0 and he does not need to activate this? What am I doing wrong? I want to prove assertions and LTL properties independently...
Here is the trace:
pan: elapsed time 0.002 seconds
To replay the error-trail, goto Simulate/Replay and select "Run"
spin -a 1_2_ConcurrentCounters_8.pml
ltl alwaysten: [] (! (((n!=10)) && ((finished==2))))
C:/cygwin/bin/gcc -DMEMLIM=1024 -O2 -DXUSAFE -w -o pan pan.c
./pan -m10000 -E -a -N alwaysten
Pid: 6980
warning: only one claim defined, -N ignored
(Spin Version 6.4.3 -- 16 December 2014)
+ Partial Order Reduction
Full statespace search for:
never claim + (alwaysten)
assertion violations + (if within scope of claim)
acceptance cycles + (fairness disabled)
invalid end states - (disabled by -E flag)
State-vector 36 byte, depth reached 57, errors: 0
475 states, stored
162 states, matched
637 transitions (= stored+matched)
0 atomic steps
hash conflicts: 0 (resolved)
Stats on memory usage (in Megabytes):
0.024 equivalent memory usage for states (stored*(State-vector + overhead))
0.291 actual memory usage for states
64.000 memory used for hash table (-w24)
0.343 memory used for DFS stack (-m10000)
64.539 total actual memory usage
unreached in proctype P
(0 of 13 states)
unreached in claim alwaysten
_spin_nvr.tmp:8, state 10, "-end-"
(1 of 10 states)
pan: elapsed time 0.001 seconds
No errors found -- did you verify all claims?
This is because your LTL is translated into a claim with an assert statement. See the following automaton.
So, without checking for assertion violations, no error can be found.
(A possible explanation of different behaviors: previous versions of Spin might translate this differently, perhaps using accept instead of assert.)
I have forked many child processes and assigned priority and core to each of them. Porcess A executes at period of 3 sec and process B at a period of 6 sec. I want them to execute in such a way that the higher priority processes should preempt lower priority ones only at predefined points and tried to acheive it with semaphores. I have used this same code snippets within the 2 processes with different array values in both.
'bubblesort_desc()' sorts the array in descending order and prints it. 'bubblesort_asc()' sorts in ascending order and prints.
while(a<3)
{
printf("time in sort1.c: %d %ld\n", (int)request.tv_sec, (long int)request.tv_nsec);
int array[SIZE] = {5, 1, 6 ,7 ,9};
semaphore_wait(global_sem);
bubblesort_desc(array, SIZE);
semaphore_post(global_sem);
semaphore_wait(global_sem);
bubblesort_asc(array, SIZE);
semaphore_post(global_sem);
semaphore_wait(global_sem);
a++;
request.tv_sec = request.tv_sec + 6;
request.tv_nsec = request.tv_nsec; //if i add 1ms here like an offset to the lower priority one, it works.
semaphore_post(global_sem);
semaphore_close(global_sem); //close the semaphore file
//sleep for the rest of the time after the process finishes execution until the period of 6
clk = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &request, NULL);
if (clk != 0 && clk != EINTR)
printf("ERROR: clock_nanosleep\n");
}
I get the output like this whenever two processes get activated at the same time. For example at time units of 6, 12,..
time in sort1.c: 10207 316296689
time now in sort.c: 10207 316296689
9
99
7
100
131
200
256
6
256
200
5
131
100
99
1
1
5
6
7
9
One process is not supposed to preempt the other while one set of sorted list is printing. But it's working as if there are no semaphores. I defined semaphores as per this link: http://linux.die.net/man/3/pthread_mutexattr_init
Can anyone tell me what can be the reason for that? Is there a better alternative than semaphores?
Its printf that's causing the ambiguous output. If the results are printed without '\n' then we get a more accurate result. But its always better to avoid printf statements for real time applications. I used trace-cmd and kernelshark to visualize the behaviour of the processes.
Every time I run my parser, it will appear "syntax error in line 1 near <>" (Because there is a subroutine yyerror(char *s)). I think that's because there is something wrong with my rules in bison.
The file (c17.isc) I want to parse.
*c17 iscas example (to test conversion program only)
*---------------------------------------------------
*
*
* total number of lines in the netlist .............. 17
* simplistically reduced equivalent fault set size = 22
* lines from primary input gates ....... 5
* lines from primary output gates ....... 2
* lines from interior gate outputs ...... 4
* lines from ** 3 ** fanout stems ... 6
*
* avg_fanin = 2.00, max_fanin = 2
* avg_fanout = 2.00, max_fanout = 2
*
*
*
*
*
1 1gat inpt 1 0 >sa1
2 2gat inpt 1 0 >sa1
3 3gat inpt 2 0 >sa0 >sa1
8 8fan from 3gat >sa1
9 9fan from 3gat >sa1
6 6gat inpt 1 0 >sa1
7 7gat inpt 1 0 >sa1
10 10gat nand 1 2 >sa1
1 8
11 11gat nand 2 2 >sa0 >sa1
9 6
14 14fan from 11gat >sa1
15 15fan from 11gat >sa1
16 16gat nand 2 2 >sa0 >sa1
2 14
20 20fan from 16gat >sa1
21 21fan from 16gat >sa1
19 19gat nand 1 2 >sa1
15 7
22 22gat nand 0 2 >sa0 >sa1
10 20
23 23gat nand 0 2 >sa0 >sa1
21 19
My flex file is as follows and it is right. You can find some information about how my scanner work here.
Error in the output of my flex file
declare.h
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# define INPT 1
# define NOR 2
# define NAND 3
# define NOT 4
# define XOR 5
# define AND 6
# define BUFF 7
# define FROM 8
flex file is
%{
# include "declare.h"
# include "parse.tab.h"
/*gi=1,it's input;gi=8,it's fanout;otherwise,it's gate*/
static int gi=-1;
static int inum=0;
struct{
char *symbol;
int val;
} symtab[]={
{"inpt", INPT},
{"nor", NOR},
{"nand", NAND},
{"not", NOT},
{"xor", XOR},
{"and", AND},
{"buff", BUFF},
{"from",FROM},
{"0",0}
};
extern FILE *yyin;
extern int yylval;
%}
%start A B C D E
DIGITS [0-9]+
BLANK [ \t\n\r\f\v\b]+
ALPHA [a-z]+
%%
"*".*\n {BEGIN A; return(COMMENT);}
<A>{DIGITS} {yylval=atoi(yytext); BEGIN B; return(NUM);}
<B>{DIGITS}{ALPHA} {yylval=atoi(yytext); BEGIN C; return(GNAME);}
<C>{DIGITS} {yylval=atoi(yytext); BEGIN D; return(OPNUM);}
<C>{DIGITS}{ALPHA} {yylval=atoi(yytext); BEGIN A; return(FR);}
<D>{DIGITS} {inum=atoi(yytext);
yylval=inum;
if(gi==1)
{BEGIN A;}
if(gi!=1)
{BEGIN E;}
return(IPNUM);
}
<E>{DIGITS} {inum--;
yylval=atoi(yytext);
if(inum<0)
{BEGIN B; return(NUM);}
else
{BEGIN E; return(ILIST);}
}
{ALPHA} {yylval=lookup(yytext);
return(GTYPE);
}
">sa"[0-1] {yylval=atoi(&yytext[yyleng-1]);return(FAULT);}
{BLANK} ;
. ;
%%
int lookup(const char *s)
{
int i;
for (i = 0; symtab[i].val != 0; i++)
{
if (strcmp(symtab[i].symbol, s) == 0)
break;
}
return(symtab[i].val);
}
The right rules in bison file are as follows
parto:
| parto COMMENT
| parto parti
;
parti: NUM
{...}
GNAME
{...}
GTYPE
{...}
| parti partii
| parti partiii
;
partii:OPNUM
{...}
IPNUM
{...}
partiv
partv
;
partiii: FR
{...}
partiv
;
partiv:
| partiv FAULT
{...}
;
partv:
| partv ILIST
{...}
;
Transferring the key comments into an answer.
The first edition of the code had a couple of problems. In the scanner code, there were lines like this:
<A>{DIGITS} { yylval=atoi(yytext); return(NUM); BEGIN B; }
You should be getting warnings about unreachable code from the BEGIN operations appearing after return. The BEGIN operations have to be executed. They aren't being executed, so you're not switching into your start states.
Michael commented:
There is no warning. I've modified it as you say and edit my codes in the question. Now I put return after BEGIN. Still, "syntax error in line 1 near <�>".
This probably means you aren't compiling the C code with enough warnings. Assuming you're using GCC, add -Wall to the compilation options for starters. There's a chance the warning requires optimization too.
Have you printed the tokens as they're returned (in the Flex scanner)? Have you compiled the Bison grammar with -DYYDEBUG? You also need to turn the debug on: yydebug = 1; in the main() program. You're probably not getting the tokens you expect when you expect them. I've not tried compiling this code yet. Tracking the tokens is key (in my experience) to getting grammars to work. Otherwise, you're running blind.
The other problem (closely related) is that you need to generate the symbolic names for FAULT etc from the grammar (bison -d grammar.y generates grammar.tab.h). You'll find that COMMENT is assigned the value 258, for example. Your scanner, though, is returning other numbers altogether because they're in declare.h. You'll have to fix this mismatch. One option is to #include "grammar.tab.h" in your scanner; this is more or less normal.
In retrospect, I think this is probably the most important observation; things seemed to revert to normal C debugging after this was resolved.
(People often include 'grammar.h' and only update 'grammar.h' if the content of 'grammar.tab.h' changes, so you don't recompile the scanner all the time).
The significance of this is that the set of tokens used by a grammar tends to be fairly stable while the actions associated with the rules change all the time as the implementation of the grammar evolves. So, if it takes enough time to be worth worrying about, you can create file grammar.h that is a copy of grammar.tab.h, but only update grammar.h when the content of grammar.tab.h changes.
cmp -s grammar.tab.h grammar.h || cp grammar.tab.h grammar.h
You'd include this in the makefile rule that converts that grammar into a C file (or an object file).
If the scanner is small enough and your machine fast enough, it may be simpler not to bother with this refinement; it mattered more in the days of 50 MHz machines with a few MiB of RAM than it does in these days of multiple cores running at 2+ GHz with a few GiB of RAM.