Before this change, we set the replyObject in the thread state on recv
with no back pointer such that stray pointers would be left in the
thread state when a reply object was completed.
The new semantics are clearer and fix this problem by doing the
following:
- tcb->tcbReply is removed and the thread state field is always used,
this was unneccessary duplication previously
- the thread state value is set to the reply object only when the thread
is in BlockedOnReply or BlockedOnRecv
- the reply contains a back pointer, replyTCB, which points to that
thread
- if a thread has its reply removed, it must be set to
ThreadState_Inactive.
- deletion is easy in the blockedOnRecv case, we just unlink the reply
and the tcb.
- deletion is complicated for blockedOnReply. If we are deleing a tcb,
we remove the actual reply object and the call chain is broken. If we
are deleting a reply, we maintain the call chain by moving the tcb to
the next reply.
- we refactor the reply object interface to solve the above.
* reply_clear: removes the reply from any connections (tcb, sc)
* reply_unlink: just unlinks the tcb and reply, and sets the thread
state to inactive
* reply_remove: removes the reply from the call chain
* reply_remove_tcb: removes the exact reply that a tcb is bound to,
as we are removing that tcb. Breaks the call chain.
43 lines
1.5 KiB
C
43 lines
1.5 KiB
C
/*
|
|
* Copyright 2019, Data61
|
|
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
|
|
* ABN 41 687 119 230.
|
|
*
|
|
* This software may be distributed and modified according to the terms of
|
|
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
|
|
* See "LICENSE_GPLv2.txt" for details.
|
|
*
|
|
* @TAG(DATA61_GPL)
|
|
*/
|
|
#ifndef __OBJECT_REPLY_H
|
|
#define __OBJECT_REPLY_H
|
|
|
|
#include <types.h>
|
|
#include <api/failures.h>
|
|
#include <object/structures.h>
|
|
|
|
/* Unlink a reply from its tcb */
|
|
static inline void reply_unlink(reply_t *reply)
|
|
{
|
|
/* check the tcb and reply are linked correctly */
|
|
assert(thread_state_get_replyObject(reply->replyTCB->tcbState) == REPLY_REF(reply));
|
|
|
|
tcb_t *tcb = reply->replyTCB;
|
|
thread_state_ptr_set_replyObject(&tcb->tcbState, REPLY_REF(0));
|
|
reply->replyTCB = NULL;
|
|
setThreadState(tcb, ThreadState_Inactive);
|
|
}
|
|
|
|
/* Push a reply object onto the call stack */
|
|
void reply_push(tcb_t *tcb_caller, tcb_t *tcb_callee, reply_t *reply, bool_t canDonate);
|
|
/* Pop the head reply from the call stack */
|
|
void reply_pop(reply_t *reply);
|
|
/* Remove a reply from the call stack - replyTCB must be in ThreadState_BlockedOnReply */
|
|
void reply_remove(reply_t *reply);
|
|
/* Remove a specific tcb, and the reply it is blocking on, from the call stack */
|
|
void reply_remove_tcb(tcb_t *tcb);
|
|
/* clear a reply object, either for deletion or reuse. Will not be
|
|
* linked to a tcb or in a call stack after this */
|
|
void reply_clear(reply_t *reply);
|
|
|
|
#endif /* __OBJECT_REPLY_H */
|