//kernel/trunk/generic/src/mm/frame.c |
---|
134,6 → 134,7 |
/** |
* Insert-sort zone into zones list |
* |
* @param newzone New zone to be inserted into zone list |
* @return zone number on success, -1 on error |
*/ |
static int zones_add_zone(zone_t *newzone) |
172,8 → 173,10 |
/** |
* Try to find a zone where can we find the frame |
* |
* @param hint Start searching in zone 'hint' |
* @param lock Lock zone if true |
* @param frame Frame number contained in zone |
* @param pzone If not null, it is used as zone hint. Zone index |
* is filled into the variable on success. |
* @return Pointer to LOCKED zone containing frame |
* |
* Assume interrupts disable |
*/ |
220,6 → 223,7 |
* |
* Assume interrupts are disabled!! |
* |
* @param order Size (2^order) of free space we are trying to find |
* @param pzone Pointer to preferred zone or NULL, on return contains zone number |
*/ |
static zone_t * find_free_zone_lock(__u8 order, int *pzone) |
468,6 → 472,9 |
/** Free frame from zone |
* |
* Assume zone is locked |
* |
* @param zone Pointer to zone from which the frame is to be freed |
* @param frame_idx Frame index relative to zone |
*/ |
static void zone_frame_free(zone_t *zone, index_t frame_idx) |
{ |
518,6 → 525,10 |
* Expect zone_t *z to point to space at least zone_conf_size large |
* |
* Assume z1 & z2 are locked |
* |
* @param z Target zone structure pointer |
* @param z1 Zone to merge |
* @param z2 Zone to merge |
*/ |
static void _zone_merge(zone_t *z, zone_t *z1, zone_t *z2) |
627,8 → 638,9 |
/** Reduce allocated block to count of order 0 frames |
* |
* The allocated block need 2^order frames of space. Reduce all frames |
* in block to order 0 and free the unneded frames. This means, that |
* when freeing the block, you have to free every frame from block. |
* in block to order 0 and free the unneeded frames. This means, that |
* when freeing the previously allocated block starting with frame_idx, |
* you have to free every frame. |
* |
* @param zone |
* @param frame_idx Index to block |
751,8 → 763,8 |
* Create new frame zone. |
* |
* @param start Physical address of the first frame within the zone. |
* @param size Size of the zone. Must be a multiple of FRAME_SIZE. |
* @param conffram Address of configuration frame |
* @param count Count of frames in zone |
* @param z Address of configuration information of zone |
* @param flags Zone flags. |
* |
* @return Initialized zone. |
793,7 → 805,11 |
} |
} |
/** Compute configuration data size for zone */ |
/** Compute configuration data size for zone |
* |
* @param count Size of zone in frames |
* @return Size of zone configuration info (in bytes) |
*/ |
__address zone_conf_size(count_t count) |
{ |
int size = sizeof(zone_t) + count*sizeof(frame_t); |
806,11 → 822,16 |
/** Create and add zone to system |
* |
* @param confframe Where configuration frame is supposed to be. |
* Always check, that we will not disturb the kernel and possibly init. |
* @param start First frame number (absolute) |
* @param count Size of zone in frames |
* @param confframe Where configuration frames are supposed to be. |
* Automatically checks, that we will not disturb the |
* kernel and possibly init. |
* If confframe is given _outside_ this zone, it is expected, |
* that the area is already marked BUSY and big enough |
* to contain zone_conf_size() amount of data |
* to contain zone_conf_size() amount of data. |
* If the confframe is inside the area, the zone free frame |
* information is modified not to include it. |
* |
* @return Zone number or -1 on error |
*/ |
//kernel/trunk/generic/src/ipc/ipcrsc.c |
---|
158,8 → 158,12 |
spinlock_lock(&TASK->lock); |
for (i=0; i < IPC_MAX_PHONES; i++) { |
if (TASK->phones[i].busy==IPC_BUSY_FREE && !atomic_get(&TASK->phones[i].active_calls)) { |
TASK->phones[i].busy = IPC_BUSY_CONNECTING; |
if (TASK->phones[i].state == IPC_PHONE_HUNGUP && \ |
atomic_get(&TASK->phones[i].active_calls) == 0) |
TASK->phones[i].state = IPC_PHONE_FREE; |
if (TASK->phones[i].state == IPC_PHONE_FREE) { |
TASK->phones[i].state = IPC_PHONE_CONNECTING; |
break; |
} |
} |
172,11 → 176,11 |
static void phone_deallocp(phone_t *phone) |
{ |
ASSERT(phone->busy == IPC_BUSY_CONNECTING); |
ASSERT(phone->state == IPC_PHONE_CONNECTING); |
ASSERT(! phone->callee); |
/* atomic operation */ |
phone->busy = IPC_BUSY_FREE; |
phone->state = IPC_PHONE_FREE; |
} |
/** Free slot from a disconnected phone |
200,6 → 204,6 |
{ |
phone_t *phone = &TASK->phones[phoneid]; |
ASSERT(phone->busy == IPC_BUSY_CONNECTING); |
ASSERT(phone->state == IPC_PHONE_CONNECTING); |
ipc_phone_connect(phone, box); |
} |
//kernel/trunk/generic/src/ipc/sysipc.c |
---|
105,9 → 105,9 |
*/ |
spinlock_lock(&answer->data.phone->lock); |
spinlock_lock(&TASK->answerbox.lock); |
if (answer->data.phone->callee) { |
if (answer->data.phone->state == IPC_PHONE_CONNECTED) { |
list_remove(&answer->data.phone->list); |
answer->data.phone->callee = 0; |
answer->data.phone->state = IPC_PHONE_SLAMMED; |
} |
spinlock_unlock(&TASK->answerbox.lock); |
spinlock_unlock(&answer->data.phone->lock); |
492,7 → 492,7 |
GET_CHECK_PHONE(phone, phoneid, return ENOENT); |
if (ipc_phone_hangup(phone)) |
if (ipc_phone_hangup(phone, 0)) |
return -1; |
return 0; |
//kernel/trunk/generic/src/ipc/ipc.c |
---|
111,7 → 111,7 |
spinlock_lock(&phone->lock); |
ASSERT(!phone->callee); |
phone->busy = IPC_BUSY_CONNECTED; |
phone->state = IPC_PHONE_CONNECTED; |
phone->callee = box; |
spinlock_lock(&box->lock); |
127,7 → 127,7 |
{ |
spinlock_initialize(&phone->lock, "phone_lock"); |
phone->callee = NULL; |
phone->busy = IPC_BUSY_FREE; |
phone->state = IPC_PHONE_FREE; |
atomic_set(&phone->active_calls, 0); |
} |
184,11 → 184,7 |
{ |
call->data.phone = phone; |
atomic_inc(&phone->active_calls); |
if (phone->busy == IPC_BUSY_CONNECTED) |
IPC_SET_RETVAL(call->data, EHANGUP); |
else |
IPC_SET_RETVAL(call->data, ENOENT); |
IPC_SET_RETVAL(call->data, err); |
_ipc_answer_free_call(call); |
} |
216,23 → 212,20 |
answerbox_t *box; |
spinlock_lock(&phone->lock); |
box = phone->callee; |
if (!box) { |
/* Trying to send over disconnected phone */ |
if (phone->state != IPC_PHONE_CONNECTED) { |
spinlock_unlock(&phone->lock); |
if (call->flags & IPC_CALL_FORWARDED) { |
IPC_SET_RETVAL(call->data, EFORWARD); |
_ipc_answer_free_call(call); |
} else { /* Simulate sending back a message */ |
if (phone->busy == IPC_BUSY_CONNECTED) |
} else { |
if (phone->state == IPC_PHONE_HUNGUP) |
ipc_backsend_err(phone, call, EHANGUP); |
else |
ipc_backsend_err(phone, call, ENOENT); |
} |
return ENOENT; |
} |
box = phone->callee; |
_ipc_call(phone, box, call); |
spinlock_unlock(&phone->lock); |
241,40 → 234,51 |
/** Disconnect phone from answerbox |
* |
* It is allowed to call disconnect on already disconnected phone |
* This call leaves the phone in HUNGUP state. The change to 'free' is done |
* lazily later. |
* |
* @param phone Phone to be hung up |
* @param aggressive If false, the phone is only marked hungup, and all |
* messages are allowed to complete. |
* If true, all messages in all queues are discarded. There |
* may still be some messages that will be 'in-transit' on |
* other CPU. |
* |
* @return 0 - phone disconnected, -1 - the phone was already disconnected |
*/ |
int ipc_phone_hangup(phone_t *phone) |
int ipc_phone_hangup(phone_t *phone, int aggressive) |
{ |
answerbox_t *box; |
call_t *call; |
spinlock_lock(&phone->lock); |
if (phone->state == IPC_PHONE_FREE || phone->state ==IPC_PHONE_HUNGUP \ |
|| phone->state == IPC_PHONE_CONNECTING) { |
spinlock_unlock(&phone->lock); |
return -1; |
} |
box = phone->callee; |
if (!box) { |
if (phone->busy == IPC_BUSY_CONNECTING) { |
spinlock_unlock(&phone->lock); |
return -1; |
if (phone->state != IPC_PHONE_SLAMMED) { |
/* Remove myself from answerbox */ |
spinlock_lock(&box->lock); |
list_remove(&phone->list); |
spinlock_unlock(&box->lock); |
if (phone->state != IPC_PHONE_SLAMMED) { |
call = ipc_call_alloc(0); |
IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); |
call->flags |= IPC_CALL_DISCARD_ANSWER; |
_ipc_call(phone, box, call); |
} |
/* Already disconnected phone */ |
phone->busy = IPC_BUSY_FREE; |
spinlock_unlock(&phone->lock); |
return 0; |
} |
spinlock_lock(&box->lock); |
list_remove(&phone->list); |
phone->callee = NULL; |
spinlock_unlock(&box->lock); |
if (aggressive && atomic_get(&phone->active_calls) > 0) { |
/* TODO: Do some stuff be VERY aggressive */ |
} |
call = ipc_call_alloc(0); |
IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); |
call->flags |= IPC_CALL_DISCARD_ANSWER; |
_ipc_call(phone, box, call); |
phone->busy = IPC_BUSY_FREE; |
phone->callee = 0; |
phone->state = IPC_PHONE_HUNGUP; |
spinlock_unlock(&phone->lock); |
return 0; |
380,7 → 384,7 |
/* Disconnect all our phones ('ipc_phone_hangup') */ |
for (i=0;i < IPC_MAX_PHONES; i++) |
ipc_phone_hangup(&task->phones[i]); |
ipc_phone_hangup(&task->phones[i], 1); |
/* Disconnect all connected irqs */ |
ipc_irq_cleanup(&task->answerbox); |
398,7 → 402,8 |
} |
/* Disconnect phone */ |
phone->callee = NULL; |
ASSERT(phone->state == IPC_PHONE_CONNECTED); |
phone->state = IPC_PHONE_SLAMMED; |
list_remove(&phone->list); |
spinlock_unlock(&phone->lock); |
411,7 → 416,21 |
spinlock_unlock(&task->answerbox.lock); |
/* Wait for all async answers to arrive */ |
while (atomic_get(&task->active_calls)) { |
while (1) { |
/* Go through all phones, until all are FREE... */ |
/* Locking not needed, no one else should modify |
* it, when we are in cleanup */ |
for (i=0;i < IPC_MAX_PHONES; i++) { |
if (task->phones[i].state == IPC_PHONE_HUNGUP && \ |
atomic_get(&task->phones[i].active_calls) == 0) |
task->phones[i].state = IPC_PHONE_FREE; |
if (task->phones[i].state != IPC_PHONE_FREE) |
break; |
} |
/* Voila, got into cleanup */ |
if (i == IPC_MAX_PHONES) |
break; |
call = ipc_wait_for_call(&task->answerbox, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE); |
ASSERT((call->flags & IPC_CALL_ANSWERED) || (call->flags & IPC_CALL_NOTIF)); |
ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC)); |