Changed the report system to use threads.

Unfortunately I need threads for this (because reports will be used in Up()/Down() and always creating a reply port is not very nice).
Does anyone have a good send/receive_data_etc() implementation? :) I hope our kernel will get that functionality.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4085 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Waldemar Kornewald 2003-07-26 18:17:26 +00:00
parent cdb26db4b8
commit ff3b40e0da
5 changed files with 78 additions and 27 deletions

View File

@ -105,10 +105,10 @@ class PPPInterface {
bool Down(); bool Down();
bool IsUp() const; bool IsUp() const;
void EnableReports(PPP_REPORT_TYPE type, port_id port, void EnableReports(PPP_REPORT_TYPE type, thread_id thread,
int32 flags = PPP_NO_REPORT_FLAGS); int32 flags = PPP_NO_REPORT_FLAGS);
void DisableReports(PPP_REPORT_TYPE type, port_id port); void DisableReports(PPP_REPORT_TYPE type, thread_id thread);
bool DoesReport(PPP_REPORT_TYPE type, port_id port); bool DoesReport(PPP_REPORT_TYPE type, thread_id thread);
bool Report(PPP_REPORT_TYPE type, int32 code, void *data, int32 length); bool Report(PPP_REPORT_TYPE type, int32 code, void *data, int32 length);
// returns false if reply was bad (or an error occured) // returns false if reply was bad (or an error occured)
@ -158,8 +158,6 @@ class PPPInterface {
List<ppp_module_info*> fModules; List<ppp_module_info*> fModules;
List<ppp_report_request> fReportRequests; List<ppp_report_request> fReportRequests;
port_id fPort;
BLocker& fLock; BLocker& fLock;
}; };

View File

@ -32,7 +32,6 @@ enum PPP_CONNECTION_REPORT_CODES {
}; };
typedef struct ppp_report_packet { typedef struct ppp_report_packet {
port_id port;
int32 type; int32 type;
int32 code; int32 code;
uint8 len; uint8 len;
@ -44,7 +43,7 @@ typedef struct ppp_report_packet {
//*********** //***********
// private // private
//*********** //***********
#define PPP_REPORT_TIMEOUT 10000 #define PPP_REPORT_TIMEOUT 10
typedef struct ppp_report_request { typedef struct ppp_report_request {
port_id port; port_id port;

View File

@ -32,8 +32,6 @@ PPPInterface::PPPInterface(driver_settings *settings, PPPInterface *parent = NUL
if(get_module(PPP_MANAGER_MODULE_NAME, (module_info**) &fManager) != B_OK) if(get_module(PPP_MANAGER_MODULE_NAME, (module_info**) &fManager) != B_OK)
fManager = NULL; fManager = NULL;
fPort = create_port(0, "PPP: reply port");
// are we a multilink subinterface? // are we a multilink subinterface?
if(parent && parent->IsMultilink()) { if(parent && parent->IsMultilink()) {
fParent = parent; fParent = parent;
@ -94,7 +92,6 @@ PPPInterface::~PPPInterface()
// put all modules (in fModules) // put all modules (in fModules)
put_module((module_info**) &fManager); put_module((module_info**) &fManager);
delete_port(fPort);
} }
@ -108,7 +105,7 @@ PPPInterface::Delete()
status_t status_t
PPPInterface::InitCheck() const PPPInterface::InitCheck() const
{ {
if(!fSettings || !fManager || fPort < 0) if(!fSettings || !fManager)
return B_ERROR; return B_ERROR;
// sub-interfaces should have a device // sub-interfaces should have a device
@ -513,14 +510,14 @@ PPPInterface::IsUp() const
void void
PPPInterface::EnableReports(PPP_REPORT_TYPE type, port_id port, PPPInterface::EnableReports(PPP_REPORT_TYPE type, thread_id thread,
int32 flags = PPP_NO_REPORT_FLAGS) int32 flags = PPP_NO_REPORT_FLAGS)
{ {
LockerHelper locker(fLock); LockerHelper locker(fLock);
ppp_report_request request; ppp_report_request request;
request.type = type; request.type = type;
request.port = port; request.thread = thread;
request.flags = flags; request.flags = flags;
fReportRequests.AddItem(request); fReportRequests.AddItem(request);
@ -528,14 +525,14 @@ PPPInterface::EnableReports(PPP_REPORT_TYPE type, port_id port,
void void
PPPInterface::DisableReports(PPP_REPORT_TYPE type, port_id port) PPPInterface::DisableReports(PPP_REPORT_TYPE type, thread_id thread)
{ {
LockerHelper locker(fLock); LockerHelper locker(fLock);
for(int32 i = 0; i < fReportRequests.CountItems(); i++) { for(int32 i = 0; i < fReportRequests.CountItems(); i++) {
ppp_report_request& request = fReportRequests.ItemAt(i); ppp_report_request& request = fReportRequests.ItemAt(i);
if(request.port != port) if(request.thread != thread)
continue; continue;
if(report.type == type) if(report.type == type)
@ -545,14 +542,14 @@ PPPInterface::DisableReports(PPP_REPORT_TYPE type, port_id port)
bool bool
PPPInterface::DoesReport(PPP_REPORT_TYPE type, port_id port) PPPInterface::DoesReport(PPP_REPORT_TYPE type, thread_id thread)
{ {
LockerHelper locker(fLock); LockerHelper locker(fLock);
for(int32 i = 0; i < fReportRequests.CountItems(); i++) { for(int32 i = 0; i < fReportRequests.CountItems(); i++) {
ppp_report_request& request = fReportRequests.ItemAt(i); ppp_report_request& request = fReportRequests.ItemAt(i);
if(request.port == port && request.type == type) if(request.thread == thread && request.type == type)
return true; return true;
} }
@ -563,7 +560,7 @@ PPPInterface::DoesReport(PPP_REPORT_TYPE type, port_id port)
bool bool
PPPInterface::Report(PPP_REPORT_TYPE type, int32 code, void *data, int32 length) PPPInterface::Report(PPP_REPORT_TYPE type, int32 code, void *data, int32 length)
{ {
if(length > PPP_REPORT_DATA_LIMIT || fPort < 0) if(length > PPP_REPORT_DATA_LIMIT)
return false; return false;
if(fReportRequests.CountItems() == 0) if(fReportRequests.CountItems() == 0)
@ -575,10 +572,10 @@ PPPInterface::Report(PPP_REPORT_TYPE type, int32 code, void *data, int32 length)
LockerHelper locker(fLock); LockerHelper locker(fLock);
int32 code, query, result; int32 code, query, result;
bool successful = true; thread_id sender;
bool acceptable = true;
report_packet report; report_packet report;
report.port = fPort;
report.type = type; report.type = type;
report.code = code; report.code = code;
report.length = length; report.length = length;
@ -587,18 +584,18 @@ PPPInterface::Report(PPP_REPORT_TYPE type, int32 code, void *data, int32 length)
for(int32 index = 0; index < fReportRequests.CountItems(); index++) { for(int32 index = 0; index < fReportRequests.CountItems(); index++) {
ppp_report_request& request = fReportRequests.ItemAt(index); ppp_report_request& request = fReportRequests.ItemAt(index);
result = write_port_etc(request.port, PPP_REPORT_CODE, &report, result = send_data_with_timeout(request.port, PPP_REPORT_CODE, &report,
sizeof(report), B_TIMEOUT, PPP_REPORT_TIMEOUT); sizeof(report), PPP_REPORT_TIMEOUT);
if(result == B_BAD_PORT_ID) { if(result == B_BAD_THREAD_ID || result == B_NO_MEMORY) {
fReportRequests.RemoveItem(request); fReportRequests.RemoveItem(request);
--index; --index;
continue; continue;
} else if(result == B_OK) { } else if(result == B_OK) {
if(request.flags & PPP_WAIT_FOR_REPLY) { if(request.flags & PPP_WAIT_FOR_REPLY) {
result = read_port_etc(fPort, &code, NULL, 0, result = receive_data_with_timeout(fPort, &code, NULL, 0,
B_TIMEOUT, PPP_REPORT_TIMEOUT); PPP_REPORT_TIMEOUT);
if(result == 0 && code != B_OK) if(result == B_OK && code != B_OK)
successful = false; successful = false;
} }
} }
@ -609,7 +606,7 @@ PPPInterface::Report(PPP_REPORT_TYPE type, int32 code, void *data, int32 length)
} }
} }
return successful; return acceptable;
} }

View File

@ -0,0 +1,43 @@
#include "KPPPUtils.h"
#include <OS.h>
// These are very simple send/receive_data functions with a timeout
// and there is a race condition beween has_data() and send/receive_data().
// Timeouts in ms.
status_t
send_data_with_timeout(thread_id thread, int32 code, void *buffer,
size_t buffer_size, uint32 timeout)
{
int32 tries;
for(tries = 0; tries < timeout; tries++) {
if(has_data(thread))
snooze(1000);
else
return send_data(thread, code, buffer, buffer_size);
}
return B_TIMED_OUT;
}
status_t
receive_data_with_timeout(thread_id *sender, int32 *code, void *buffer,
size_t buffer_size, uint32 timeout)
{
int32 tries;
for(tries = 0; tries < timeout; tries++) {
if(has_data(find_thread(NULL))) {
snooze(1000);
continue;
}
*code = receive_data(sender, buffer, buffer_size);
return B_OK;
}
return B_TIMED_OUT;
}

View File

@ -0,0 +1,14 @@
#ifndef _K_PPP_UTILS__H
#define _K_PPP_UTILS__H
// These are very simple send/receive_data functions with a timeout
// and there is a race condition beween has_data() and send/receive_data().
// Timeouts in ms.
status_t send_data_with_timeout(thread_id thread, int32 code, void *buffer,
size_t buffer_size, uint32 timeout);
status_t receive_data_with_timeout(thread_id *sender, int32 *code, void *buffer,
size_t buffer_size, uint32 timeout);
#endif