GCOV Execution Analysis for event.c
The left column is the number of times the code was executed
during the unit test suites.
Exec | Code | Line # | |
---|---|---|---|
Source:event.c | 1 | ||
Graph:.libs/event.gcno | 2 | ||
Data:.libs/event.gcda | 3 | ||
Runs:378 | 4 | ||
Programs:378 | 5 | ||
/* -*- linux-c -*- | 6 | ||
* | 7 | ||
* Copyright (c) 2003 by Intel Corp. | 8 | ||
* (C) Copyright IBM Corp. 2003-2004 | 9 | ||
* | 10 | ||
* This program is distributed in the hope that it will be useful, | 11 | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. This | 13 | ||
* file and program are licensed under a BSD style license. See | 14 | ||
* the Copying file included with the OpenHPI distribution for | 15 | ||
* full licensing terms. | 16 | ||
* | 17 | ||
* Authors: | 18 | ||
* Louis Zhuang < address removed > | 19 | ||
* David Judkovics < address removed > | 20 | ||
* Sean Dague <http://dague.net/sean> | 21 | ||
* Renier Morales < address removed > | 22 | ||
* Racing Guo < address removed > | 23 | ||
*/ | 24 | ||
25 | |||
#include <unistd.h> | 26 | ||
#include <stdio.h> | 27 | ||
#include <stdlib.h> | 28 | ||
#include <string.h> | 29 | ||
30 | |||
#include <openhpi.h> | 31 | ||
#include <oh_event.h> | 32 | ||
#include <glib.h> | 33 | ||
34 | |||
#define OH_THREAD_SLEEP_TIME 2 * G_USEC_PER_SEC | 35 | ||
36 | |||
static gboolean oh_is_threaded = FALSE; | 37 | ||
GAsyncQueue *oh_process_q = NULL; | 38 | ||
GCond *oh_thread_wait = NULL; | 39 | ||
GThread *oh_event_thread = NULL; | 40 | ||
GError *oh_event_thread_error = NULL; | 41 | ||
GMutex *oh_thread_mutex = NULL; | 42 | ||
43 | |||
gboolean oh_run_threaded() | 44 | ||
5 | { | 45 | |
5 | return oh_is_threaded; | 46 | |
} | 47 | ||
48 | |||
static gpointer oh_event_thread_loop(gpointer data) | 49 | ||
0 | { | 50 | |
0 | GTimeVal time; | 51 | |
52 | |||
0 | while(oh_run_threaded()) { | 53 | |
0 | dbg("About to run through the event loop"); | 54 | |
55 | |||
0 | oh_get_events(); | 56 | |
57 | |||
0 | g_get_current_time(&time); | 58 | |
0 | g_time_val_add(&time, OH_THREAD_SLEEP_TIME); | 59 | |
0 | dbg("Going to sleep"); | 60 | |
61 | |||
0 | if (g_cond_timed_wait(oh_thread_wait, oh_thread_mutex, &time)) | 62 | |
0 | dbg("SIGNALED: Got signal from plugin"); | 63 | |
else | 64 | ||
0 | dbg("TIMEDOUT: Woke up, am looping again"); | 65 | |
} | 66 | ||
0 | g_thread_exit(0); | 67 | |
0 | return 0; | 68 | |
} | 69 | ||
70 | |||
/* | 71 | ||
* The following is required to set up the thread state for | 72 | ||
* the use of async queues. This is true even if we aren't | 73 | ||
* using live threads. | 74 | ||
*/ | 75 | ||
int oh_event_init() | 76 | ||
374 | { | 77 | |
374 | struct oh_global_param threaded_param = { .type = OPENHPI_THREADED }; | 78 | |
79 | |||
374 | trace("Attempting to init event"); | 80 | |
374 | if (!g_thread_supported()) { | 81 | |
374 | trace("Initializing thread support"); | 82 | |
374 | g_thread_init(NULL); | 83 | |
} else { | 84 | ||
0 | trace("Already supporting threads"); | 85 | |
} | 86 | ||
374 | trace("Setting up event processing queue"); | 87 | |
374 | oh_process_q = g_async_queue_new(); | 88 | |
89 | |||
374 | oh_get_global_param(&threaded_param); | 90 | |
374 | if (threaded_param.u.threaded) { | 91 | |
0 | oh_is_threaded = TRUE; | 92 | |
0 | oh_thread_wait = g_cond_new(); | 93 | |
0 | oh_thread_mutex = g_mutex_new(); | 94 | |
0 | oh_event_thread = g_thread_create(oh_event_thread_loop, | 95 | |
NULL, FALSE, &oh_event_thread_error); | 96 | ||
} | 97 | ||
98 | |||
374 | return 1; | 99 | |
} | 100 | ||
101 | |||
int oh_event_final() | 102 | ||
0 | { | 103 | |
0 | g_async_queue_unref(oh_process_q); | 104 | |
0 | if(oh_run_threaded()) { | 105 | |
0 | g_mutex_free(oh_thread_mutex); | 106 | |
0 | g_cond_free(oh_thread_wait); | 107 | |
} | 108 | ||
0 | return 1; | 109 | |
} | 110 | ||
111 | |||
/* | 112 | ||
* Event processing is split up into 2 stages | 113 | ||
* | 114 | ||
* | 115 | ||
*/ | 116 | ||
117 | |||
static SaErrorT harvest_events_for_handler(struct oh_handler *h) | 118 | ||
380 | { | 119 | |
380 | struct oh_event event; | 120 | |
380 | struct oh_event *e2; | 121 | |
122 | |||
380 | SaErrorT error = SA_OK; | 123 | |
124 | |||
4783 | do { | 125 | |
4783 | error = h->abi->get_event(h->hnd, &event); | 126 | |
4783 | if(error < 1) { | 127 | |
380 | trace("Handler is out of Events"); | 128 | |
} else { | 129 | ||
4403 | trace("Found event for handler %p", h); | 130 | |
4403 | e2 = oh_dup_oh_event(&event); | 131 | |
4403 | e2->hid = h->id; | 132 | |
4403 | g_async_queue_push(oh_process_q, e2); | 133 | |
} | 134 | ||
4783 | } while(error > 0); | 135 | |
136 | |||
380 | return error; | 137 | |
} | 138 | ||
139 | |||
SaErrorT oh_harvest_events() | 140 | ||
380 | { | 141 | |
380 | SaErrorT error = SA_ERR_HPI_ERROR; | 142 | |
380 | unsigned int hid = 0, next_hid; | 143 | |
380 | struct oh_handler *h = NULL; | 144 | |
145 | |||
380 | data_access_lock(); | 146 | |
380 | oh_lookup_next_handler(hid, &next_hid); | 147 | |
760 | while (next_hid) { | 148 | |
380 | hid = next_hid; | 149 | |
380 | h = oh_lookup_handler(hid); | 150 | |
380 | if (harvest_events_for_handler(h) == SA_OK && error) | 151 | |
0 | error = SA_OK; | 152 | |
153 | |||
380 | oh_lookup_next_handler(hid, &next_hid); | 154 | |
} | 155 | ||
380 | data_access_unlock(); | 156 | |
157 | |||
380 | return error; | 158 | |
} | 159 | ||
160 | |||
static SaErrorT oh_add_event_to_del(SaHpiDomainIdT did, struct oh_hpi_event *e) | 161 | ||
4403 | { | 162 | |
4403 | struct oh_global_param logsev_param = { .type = OPENHPI_LOG_ON_SEV }; | 163 | |
4403 | struct oh_domain *d; | 164 | |
4403 | SaErrorT rv = SA_OK; | 165 | |
166 | |||
4403 | oh_get_global_param(&logsev_param); | 167 | |
168 | |||
4403 | if (e->event.Severity <= logsev_param.u.log_on_sev) { /* less is more */ | 169 | |
/* yes, we need to add real domain support later here */ | 170 | ||
4403 | d = oh_get_domain(did); | 171 | |
4403 | if(d) { | 172 | |
4403 | rv = oh_el_append(d->del, &e->event, &e->rdr, &e->res); | 173 | |
4403 | oh_release_domain(d); | 174 | |
} else { | 175 | ||
0 | rv = SA_ERR_HPI_ERROR; | 176 | |
} | 177 | ||
} | 178 | ||
4403 | return rv; | 179 | |
} | 180 | ||
181 | |||
static int process_hpi_event(struct oh_event *full_event) | 182 | ||
4403 | { | 183 | |
4403 | int i; | 184 | |
4403 | GArray *sessions = NULL; | 185 | |
4403 | SaHpiSessionIdT sid; | 186 | |
4403 | struct oh_domain *d = NULL; | 187 | |
4403 | struct oh_hpi_event *e = NULL; | 188 | |
189 | |||
/* We take the domain lock for the whole function here */ | 190 | ||
191 | |||
4403 | d = oh_get_domain(full_event->did); | 192 | |
4403 | if(!d) { | 193 | |
0 | dbg("Domain %d doesn't exist", full_event->did); | 194 | |
0 | return -1; /* FIXME: should this be -1? */ | 195 | |
} | 196 | ||
197 | |||
4403 | e = &(full_event->u.hpi_event); | 198 | |
199 | |||
4403 | if (e->res.ResourceCapabilities & SAHPI_CAPABILITY_MANAGED_HOTSWAP | 200 | |
&& e->event.EventType == SAHPI_ET_HOTSWAP) { | 201 | ||
10 | hotswap_push_event(&hs_eq, full_event); | 202 | |
10 | trace("Pushed hotswap event"); | 203 | |
} | 204 | ||
205 | |||
/* FIXME: Add event to DEL */ | 206 | ||
4403 | trace("About to add to EL"); | 207 | |
4403 | oh_add_event_to_del(d->id, e); | 208 | |
4403 | trace("Added event to EL"); | 209 | |
210 | |||
/* | 211 | ||
* TODO: Here is where we need the SESSION MULTIPLEXING code | 212 | ||
*/ | 213 | ||
214 | |||
/* FIXME: yes, we need to figure out the real domain at some point */ | 215 | ||
4403 | trace("About to get session list"); | 216 | |
4403 | sessions = oh_list_sessions(oh_get_default_domain_id()); | 217 | |
4403 | trace("process_hpi_event, done oh_list_sessions"); | 218 | |
219 | |||
/* multiplex event to the appropriate sessions */ | 220 | ||
8806 | for(i = 0; i < sessions->len; i++) { | 221 | |
4403 | SaHpiBoolT is_subscribed = SAHPI_FALSE; | 222 | |
4403 | sid = g_array_index(sessions, SaHpiSessionIdT, i); | 223 | |
224 | |||
4403 | oh_get_session_subscription(sid, &is_subscribed); | 225 | |
4403 | if(is_subscribed) { | 226 | |
0 | oh_queue_session_event(sid, full_event); | 227 | |
} | 228 | ||
} | 229 | ||
4403 | g_array_free(sessions, TRUE); | 230 | |
4403 | trace("process_hpi_event, done multiplex event => sessions"); | 231 | |
232 | |||
4403 | oh_release_domain(d); | 233 | |
4403 | trace("process_hpi_event, done oh_release_domain"); | 234 | |
235 | |||
4403 | return 0; | 236 | |
} | 237 | ||
238 | |||
static int process_resource_event(struct oh_event *e) | 239 | ||
1099 | { | 240 | |
1099 | int rv; | 241 | |
1099 | RPTable *rpt = NULL; | 242 | |
1099 | struct oh_domain *d = NULL; | 243 | |
1099 | struct oh_event hpie; | 244 | |
245 | |||
1099 | d = oh_get_domain(e->did); | 246 | |
1099 | if(!d) { | 247 | |
0 | dbg("Domain %d doesn't exist", e->did); | 248 | |
0 | return -1; | 249 | |
} | 250 | ||
1099 | rpt = &(d->rpt); | 251 | |
252 | |||
1099 | memset(&hpie, 0, sizeof(hpie)); | 253 | |
1099 | if (e->type == OH_ET_RESOURCE_DEL) { | 254 | |
1 | rv = oh_remove_resource(rpt,e->u.res_event.entry.ResourceId); | 255 | |
1 | trace("Resource %d in Domain %d has been REMOVED.", | 256 | |
e->u.res_event.entry.ResourceId, | 257 | ||
e->did); | 258 | ||
259 | |||
1 | hpie.did = e->did; | 260 | |
1 | hpie.u.hpi_event.event.Severity = e->u.res_event.entry.ResourceSeverity; | 261 | |
1 | hpie.u.hpi_event.event.Source = e->u.res_event.entry.ResourceId; | 262 | |
1 | hpie.u.hpi_event.event.EventType = SAHPI_ET_RESOURCE; | 263 | |
1 | hpie.u.hpi_event.event.EventDataUnion.ResourceEvent.ResourceEventType = | 264 | |
SAHPI_RESE_RESOURCE_FAILURE; | 265 | ||
266 | |||
} else { | 267 | ||
1098 | struct oh_resource_data *rd = g_malloc0(sizeof(struct oh_resource_data)); | 268 | |
269 | |||
1098 | if (!rd) { | 270 | |
0 | dbg("Couldn't allocate resource data"); | 271 | |
0 | return SA_ERR_HPI_OUT_OF_MEMORY; | 272 | |
} | 273 | ||
274 | |||
1098 | rd->hid = e->hid; | 275 | |
1098 | rd->controlled = 0; | 276 | |
1098 | rd->auto_extract_timeout = get_default_hotswap_auto_extract_timeout(); | 277 | |
278 | |||
1098 | rv = oh_add_resource(rpt,&(e->u.res_event.entry),rd,0); | 279 | |
1098 | trace("Resource %d in Domain %d has been ADDED.", | 280 | |
e->u.res_event.entry.ResourceId, | 281 | ||
e->did); | 282 | ||
283 | |||
1098 | hpie.did = e->did; | 284 | |
1098 | hpie.u.hpi_event.event.Severity = e->u.res_event.entry.ResourceSeverity; | 285 | |
1098 | hpie.u.hpi_event.event.Source = e->u.res_event.entry.ResourceId; | 286 | |
1098 | hpie.u.hpi_event.event.EventType = SAHPI_ET_RESOURCE; | 287 | |
1098 | hpie.u.hpi_event.event.EventDataUnion.ResourceEvent.ResourceEventType = | 288 | |
SAHPI_RESE_RESOURCE_ADDED; | 289 | ||
} | 290 | ||
1099 | oh_release_domain(d); | 291 | |
292 | |||
1099 | if (rv == SA_OK) { | 293 | |
1099 | rv = process_hpi_event(&hpie); | 294 | |
} | 295 | ||
296 | |||
1099 | return rv; | 297 | |
} | 298 | ||
299 | |||
static int process_rdr_event(struct oh_event *e) | 300 | ||
2928 | { | 301 | |
2928 | int rv; | 302 | |
2928 | SaHpiResourceIdT rid = e->u.rdr_event.parent; | 303 | |
2928 | RPTable *rpt = NULL; | 304 | |
2928 | struct oh_domain *d = NULL; | 305 | |
2928 | struct oh_event hpie; | 306 | |
307 | |||
308 | |||
2928 | d = oh_get_domain(e->did); | 309 | |
310 | |||
/* get the RPT for this domain */ | 311 | ||
2928 | if(!d) { | 312 | |
0 | dbg("Domain %d doesn't exist", e->did); | 313 | |
0 | return -1; | 314 | |
} | 315 | ||
2928 | rpt = &(d->rpt); | 316 | |
317 | |||
2928 | if (e->type == OH_ET_RDR_DEL) { /* DELETE event */ | 318 | |
319 | |||
0 | if (!(rv = oh_remove_rdr(rpt, rid, e->u.rdr_event.rdr.RecordId)) ) { | 320 | |
0 | dbg("SUCCESS: RDR %x in Resource %d in Domain %d has been REMOVED.", | 321 | |
e->u.rdr_event.rdr.RecordId, rid, e->did); | 322 | ||
} else { | 323 | ||
0 | dbg("FAILED: RDR %x in Resource %d in Domain %d has NOT been REMOVED.", | 324 | |
e->u.rdr_event.rdr.RecordId, rid, e->did); | 325 | ||
} | 326 | ||
327 | |||
/* build event for event queue */ | 328 | ||
329 | |||
} else { /* ADD event */ | 330 | ||
331 | |||
2928 | if(!(rv = oh_add_rdr(rpt, rid, &(e->u.rdr_event.rdr), NULL, 0))) { | 332 | |
2928 | dbg("SUCCES: RDR %x in Resource %d in Domain %d has been ADDED.", | 333 | |
e->u.rdr_event.rdr.RecordId, rid, e->did); | 334 | ||
} else { | 335 | ||
0 | dbg("FAILED: RDR %x in Resource %d in Domain %d has NOT been ADDED.", | 336 | |
e->u.rdr_event.rdr.RecordId, rid, e->did); | 337 | ||
} | 338 | ||
339 | |||
/* build event for event queue */ | 340 | ||
2928 | hpie.did = e->did; | 341 | |
342 | |||
//hpie.u.hpi_event.event.Severity = e->u.rdr_event.rdr.RdrType; | 343 | ||
2928 | hpie.u.hpi_event.event.Source = e->u.rdr_event.parent; | 344 | |
2928 | hpie.u.hpi_event.event.EventType = e->u.rdr_event.rdr.RdrType; | 345 | |
2928 | hpie.u.hpi_event.rdr = e->u.rdr_event.rdr; | 346 | |
// hpie.u.hpi_event.event.EventDataUnion.ResourceEvent.ResourceEventType = | 347 | ||
// SAHPI_RESE_RESOURCE_ADDED; | 348 | ||
/* | 349 | ||
switch (e->u.rdr_event.rdr.RdrType) { | 350 | ||
case SAHPI_NO_RECORD: | 351 | ||
dbg("SAHPI_NO_RECORD: process_rdr_event"); | 352 | ||
break; | 353 | ||
case SAHPI_CTRL_RDR:. | 354 | ||
break; | 355 | ||
case SAHPI_SENSOR_RDR; | 356 | ||
break; | 357 | ||
case SAHPI_INVENTORY_RDR; | 358 | ||
hpie.u.hpi_event | 359 | ||
break; | 360 | ||
case SAHPI_WATCHDOG_RDR; | 361 | ||
break; | 362 | ||
case SAHPI_ANNUNCIATOR_RDR; | 363 | ||
break; | 364 | ||
default: | 365 | ||
dbg("ERROR: process_rdr_event, unknown SaHpiRdrTypeT Type"); | 366 | ||
break; | 367 | ||
} | 368 | ||
*/ | 369 | ||
} | 370 | ||
371 | |||
2928 | oh_release_domain(d); | 372 | |
373 | |||
2928 | if (rv == SA_OK) { | 374 | |
2928 | rv = process_hpi_event(&hpie); | 375 | |
2928 | dbg("process_rdr_event, done process_hpi_event"); | 376 | |
} | 377 | ||
378 | |||
2928 | return rv; | 379 | |
380 | |||
/* need this after different type rdr events are processed above FIXME:DJ | 381 | ||
otherwise rdr events are never palced on eventq | 382 | ||
if(rv == SA_OK) { | 383 | ||
rv = process_hpi_event(&hpie); | 384 | ||
} | 385 | ||
*/ | 386 | ||
} | 387 | ||
388 | |||
SaErrorT oh_process_events() | 389 | ||
4783 | { | 390 | |
4783 | struct oh_event *e; | 391 | |
392 | |||
4783 | while((e = g_async_queue_try_pop(oh_process_q)) != NULL) { | 393 | |
394 | |||
/* FIXME: add real check if handler is allowed to push event | 395 | ||
to the domain id in the event */ | 396 | ||
4403 | if((e->did != oh_get_default_domain_id()) && | 397 | |
(e->did != SAHPI_UNSPECIFIED_DOMAIN_ID)) { | 398 | ||
0 | dbg("Domain Id %d not valid for event", e->did); | 399 | |
0 | g_free(e); | 400 | |
0 | continue; | 401 | |
} | 402 | ||
403 | |||
4403 | switch(e->type) { | 404 | |
case OH_ET_RESOURCE: | 405 | ||
1098 | trace("Event Type = Resource"); | 406 | |
1098 | process_resource_event(e); | 407 | |
1098 | break; | 408 | |
case OH_ET_RESOURCE_DEL: | 409 | ||
1 | trace("Event Type = Resource Delete"); | 410 | |
1 | process_resource_event(e); | 411 | |
1 | break; | 412 | |
case OH_ET_RDR: | 413 | ||
2928 | trace("Event Type = RDR"); | 414 | |
2928 | process_rdr_event(e); | 415 | |
2928 | break; | 416 | |
case OH_ET_RDR_DEL: | 417 | ||
0 | trace("Event Type = RDR Delete"); | 418 | |
0 | process_rdr_event(e); | 419 | |
0 | break; | 420 | |
case OH_ET_HPI: | 421 | ||
376 | trace("Event Type = HPI Event"); | 422 | |
376 | process_hpi_event(e); | 423 | |
376 | break; | 424 | |
default: | 425 | ||
0 | trace("Event Type = Unknown Event"); | 426 | |
} | 427 | ||
} | 428 | ||
380 | g_free(e); | 429 | |
380 | return SA_OK; | 430 | |
} | 431 | ||
432 | |||
SaErrorT oh_get_events() | 433 | ||
380 | { | 434 | |
380 | SaErrorT rv = SA_OK; | 435 | |
436 | |||
380 | dbg("About to harvest events in the loop"); | 437 | |
380 | rv = oh_harvest_events(); | 438 | |
380 | if(rv != SA_OK) { | 439 | |
380 | dbg("Error on harvest of events."); | 440 | |
} | 441 | ||
442 | |||
380 | rv = oh_process_events(); | 443 | |
380 | if(rv != SA_OK) { | 444 | |
0 | dbg("Error on processing of events, aborting"); | 445 | |
} | 446 | ||
447 | |||
380 | process_hotswap_policy(); | 448 | |
449 | |||
380 | return rv; | 450 | |
} | 451 |