part_blk: Improve multiple client support

Increase size of block session backing store so it can handle maximum supported
packet size. Synchronize client threads during packet allocation.

Fixes #276
This commit is contained in:
Sebastian Sumpf 2012-07-11 14:51:42 +02:00 committed by Norman Feske
parent abd09e419f
commit 5f33704155

View File

@ -11,18 +11,24 @@
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
*/ */
#include <base/allocator_avl.h> #include <base/allocator_avl.h>
#include <base/semaphore.h>
#include <block_session/connection.h> #include <block_session/connection.h>
#include "part_blk.h" #include "part_blk.h"
using namespace Genode; using namespace Genode;
/**
* Used to block until a packet has been freed
*/
static Semaphore _alloc_sem(0);
namespace Partition { namespace Partition {
size_t _blk_cnt; size_t _blk_cnt;
size_t _blk_size; size_t _blk_size;
Allocator_avl _block_alloc(env()->heap()); Allocator_avl _block_alloc(env()->heap());
Block::Connection _blk(&_block_alloc); Block::Connection _blk(&_block_alloc, 4 * MAX_PACKET_SIZE);
Partition *_part_list[MAX_PARTITIONS]; /* contains pointers to valid partittions or 0 */ Partition *_part_list[MAX_PARTITIONS]; /* contains pointers to valid partittions or 0 */
@ -84,15 +90,8 @@ namespace Partition {
Lock::Guard guard(_lock); Lock::Guard guard(_lock);
Block::Packet_descriptor::Opcode op = write ? Block::Packet_descriptor::WRITE Block::Packet_descriptor::Opcode op = write ? Block::Packet_descriptor::WRITE
: Block::Packet_descriptor::READ; : Block::Packet_descriptor::READ;
_p = Block::Packet_descriptor(_blk.dma_alloc_packet(_blk_size * count),
try {
_p = Block::Packet_descriptor( _blk.dma_alloc_packet(_blk_size * count),
op, blk_nr, count); op, blk_nr, count);
} catch (Block::Session::Tx::Source::Packet_alloc_failed) {
PERR("Packet overrun!");
_p = _blk.tx()->get_acked_packet();
throw Io_error();
}
} }
void submit_request() void submit_request()
@ -101,6 +100,10 @@ namespace Partition {
_blk.tx()->submit_packet(_p); _blk.tx()->submit_packet(_p);
_p = _blk.tx()->get_acked_packet(); _p = _blk.tx()->get_acked_packet();
/* unblock clients that possibly wait for packet stream allocations */
if (_alloc_sem.cnt() < 0)
_alloc_sem.up();
if (!_p.succeeded()) { if (!_p.succeeded()) {
PERR("Could not access block %zu", _p.block_number()); PERR("Could not access block %zu", _p.block_number());
throw Io_error(); throw Io_error();
@ -198,16 +201,25 @@ namespace Partition {
unsigned long curr_count = min<unsigned long>(count, max_packets()); unsigned long curr_count = min<unsigned long>(count, max_packets());
bytes = curr_count * _blk_size; bytes = curr_count * _blk_size;
bool alloc = false;
while (!alloc) {
try {
Sector sec(lba, curr_count, write);
if (!write) {
sec.submit_request();
memcpy(buf, sec.addr<void *>(), bytes);
}
else {
memcpy(sec.addr<void *>(), buf, bytes);
sec.submit_request();
}
Sector sec(lba, curr_count, write); alloc = true;
} catch (Block::Session::Tx::Source::Packet_alloc_failed) {
if (!write) { /* block */
sec.submit_request(); _alloc_sem.down();
memcpy(buf, sec.addr<void *>(), bytes); }
}
else {
memcpy(sec.addr<void *>(), buf, bytes);
sec.submit_request();
} }
lba += curr_count; lba += curr_count;