4 #include <minix/config.h>
7 #include <minix/const.h>
8 #include <minix/type.h>
12 #include <minix/syslib.h>
13 #include <minix/sysutil.h>
14 #include <minix/sys_config.h>
19 #define ASYN_NR (2*_NR_PROCS)
20 static asynmsg_t msgtable
[ASYN_NR
];
21 static int first_slot
= 0, next_slot
= 0;
22 static int initialized
= 0;
24 /*===========================================================================*
26 *===========================================================================*/
27 int asynsend3(dst
, mp
, fl
)
32 int i
, r
, src_ind
, dst_ind
;
34 static int inside
= 0;
37 /* Debug printf() causes asynchronous sends? */
38 if (inside
) /* Panic will not work either then, so exit */
44 /* Initialize table by marking all entries empty */
45 for (i
= 0; i
< ASYN_NR
; i
++) msgtable
[i
].flags
= AMF_EMPTY
;
50 /* Update first_slot. That is, find the first not-completed slot by the
51 * kernel since the last time we sent this table (e.g., the receiving end of
52 * the message wasn't ready yet).
54 for (; first_slot
< next_slot
; first_slot
++) {
55 flags
= msgtable
[first_slot
].flags
;
56 if ((flags
& (AMF_VALID
|AMF_DONE
)) == (AMF_VALID
|AMF_DONE
)) {
57 /* Marked in use by us (VALID) and processed by the kernel */
58 if (msgtable
[first_slot
].result
!= OK
) {
60 printf("asynsend: found entry %d with error %d\n",
61 first_slot
, msgtable
[first_slot
].result
);
63 needack
= (flags
& (AMF_NOTIFY
|AMF_NOTIFY_ERR
));
68 if (flags
!= AMF_EMPTY
)
69 /* Found first not-completed table entry */
73 /* Reset to the beginning of the table when all messages are completed */
74 if (first_slot
>= next_slot
&& !needack
)
75 next_slot
= first_slot
= 0;
77 /* Can the table handle one more message? */
78 if (next_slot
>= ASYN_NR
) {
79 /* We're full; tell the kernel to stop processing for now */
80 if ((r
= senda(NULL
, 0)) != OK
)
81 panic("asynsend: senda failed: %d", r
);
83 /* Move all unprocessed messages to the beginning */
85 for (src_ind
= first_slot
; src_ind
< next_slot
; src_ind
++) {
86 flags
= msgtable
[src_ind
].flags
;
88 /* Skip empty entries */
89 if (flags
== AMF_EMPTY
) continue;
91 /* and completed entries only if result is OK or if error
92 * doesn't need to be acknowledged */
93 if ((flags
& (AMF_VALID
|AMF_DONE
)) == (AMF_VALID
|AMF_DONE
)) {
94 if (msgtable
[src_ind
].result
== OK
)
99 "asynsend: found entry %d with error %d\n",
100 src_ind
, msgtable
[src_ind
].result
);
102 if (!(flags
& (AMF_NOTIFY
|AMF_NOTIFY_ERR
)))
103 /* Don't need to ack this error */
109 /* Copy/move in use entry */
111 printf("asynsend: copying entry %d to %d\n", src_ind
, dst_ind
);
113 if (src_ind
!= dst_ind
) msgtable
[dst_ind
] = msgtable
[src_ind
];
117 /* Mark unused entries empty */
118 for (i
= dst_ind
; i
< ASYN_NR
; i
++) msgtable
[i
].flags
= AMF_EMPTY
;
122 if (next_slot
>= ASYN_NR
) /* Cleanup failed */
123 panic("asynsend: msgtable full");
126 fl
|= AMF_VALID
; /* Mark in use */
127 msgtable
[next_slot
].dst
= dst
;
128 msgtable
[next_slot
].msg
= *mp
;
129 msgtable
[next_slot
].flags
= fl
; /* Has to be last. The kernel
130 * scans this table while we
135 assert(next_slot
>= first_slot
);
136 len
= next_slot
- first_slot
;
137 assert(first_slot
+ len
<= ASYN_NR
);
142 /* Tell the kernel to rescan the table */
143 return senda(&msgtable
[first_slot
], len
);
146 /*===========================================================================*
148 *===========================================================================*/
149 int asyn_geterror(endpoint_t
*dst
, message
*msg
, int *err
)
151 int src_ind
, flags
, result
;
153 if (!initialized
) return(0);
155 for (src_ind
= 0; src_ind
< next_slot
; src_ind
++) {
156 flags
= msgtable
[src_ind
].flags
;
157 result
= msgtable
[src_ind
].result
;
159 /* Find a message that has been completed with an error */
160 if ((flags
& (AMF_VALID
|AMF_DONE
)) == (AMF_VALID
|AMF_DONE
)) {
161 if (result
!= OK
&& (flags
& (AMF_NOTIFY
|AMF_NOTIFY_ERR
))) {
163 if (dst
!= NULL
) *dst
= msgtable
[src_ind
].dst
;
164 if (msg
!= NULL
) *msg
= msgtable
[src_ind
].msg
;
165 if (err
!= NULL
) *err
= result
;
167 /* Acknowledge error so it can be cleaned up upon next
169 msgtable
[src_ind
].result
= OK
;