orb: reduce size of SubscriberData struct (#4771)

- priority field uses only the lower 8 bits, so we can merge with the
  update_reported flag
- orb_set_interval is not used often, so make the necessary data an
  optional pointer and alloc only when needed.

Memory savings:
- pixracer (w. ekf2): 7.3kB
- pixhawk: 5.3kB
This commit is contained in:
Beat Küng
2016-06-22 15:28:23 +02:00
committed by Lorenz Meier
parent dfa2ec8c6c
commit e7f31393bc
4 changed files with 133 additions and 42 deletions
+51 -15
View File
@@ -127,7 +127,7 @@ uORB::DeviceNode::open(struct file *filp)
sd->generation = _generation; sd->generation = _generation;
/* set priority */ /* set priority */
sd->priority = _priority; sd->set_priority(_priority);
filp->f_priv = (void *)sd; filp->f_priv = (void *)sd;
@@ -157,7 +157,10 @@ uORB::DeviceNode::close(struct file *filp)
SubscriberData *sd = filp_to_sd(filp); SubscriberData *sd = filp_to_sd(filp);
if (sd != nullptr) { if (sd != nullptr) {
hrt_cancel(&sd->update_call); if (sd->update_interval) {
hrt_cancel(&sd->update_interval->update_call);
}
remove_internal_subscriber(); remove_internal_subscriber();
delete sd; delete sd;
sd = nullptr; sd = nullptr;
@@ -209,13 +212,13 @@ uORB::DeviceNode::read(struct file *filp, char *buffer, size_t buflen)
} }
/* set priority */ /* set priority */
sd->priority = _priority; sd->set_priority(_priority);
/* /*
* Clear the flag that indicates that an update has been reported, as * Clear the flag that indicates that an update has been reported, as
* we have just collected it. * we have just collected it.
*/ */
sd->update_reported = false; sd->set_update_reported(false);
px4_leave_critical_section(flags); px4_leave_critical_section(flags);
@@ -294,16 +297,43 @@ uORB::DeviceNode::ioctl(struct file *filp, int cmd, unsigned long arg)
*(bool *)arg = appears_updated(sd); *(bool *)arg = appears_updated(sd);
return OK; return OK;
case ORBIOCSETINTERVAL: case ORBIOCSETINTERVAL: {
sd->update_interval = arg; int ret = PX4_OK;
return OK; lock();
if (arg == 0) {
if (sd->update_interval) {
delete(sd->update_interval);
sd->update_interval = nullptr;
}
} else {
if (sd->update_interval) {
sd->update_interval->interval = arg;
} else {
sd->update_interval = new UpdateIntervalData();
if (sd->update_interval) {
memset(&sd->update_interval->update_call, 0, sizeof(hrt_call));
sd->update_interval->interval = arg;
} else {
ret = -ENOMEM;
}
}
}
unlock();
return ret;
}
case ORBIOCGADVERTISER: case ORBIOCGADVERTISER:
*(uintptr_t *)arg = (uintptr_t)this; *(uintptr_t *)arg = (uintptr_t)this;
return OK; return OK;
case ORBIOCGPRIORITY: case ORBIOCGPRIORITY:
*(int *)arg = sd->priority; *(int *)arg = sd->priority();
return OK; return OK;
case ORBIOCSETQUEUESIZE: case ORBIOCSETQUEUESIZE:
@@ -312,7 +342,13 @@ uORB::DeviceNode::ioctl(struct file *filp, int cmd, unsigned long arg)
return update_queue_size(arg); return update_queue_size(arg);
case ORBIOCGETINTERVAL: case ORBIOCGETINTERVAL:
*(unsigned *)arg = sd->update_interval; if (sd->update_interval) {
*(unsigned *)arg = sd->update_interval->interval;
} else {
*(unsigned *)arg = 0;
}
return OK; return OK;
default: default:
@@ -443,7 +479,7 @@ uORB::DeviceNode::appears_updated(SubscriberData *sd)
/* /*
* Handle non-rate-limited subscribers. * Handle non-rate-limited subscribers.
*/ */
if (sd->update_interval == 0) { if (sd->update_interval == nullptr) {
ret = true; ret = true;
break; break;
} }
@@ -455,7 +491,7 @@ uORB::DeviceNode::appears_updated(SubscriberData *sd)
* behaviour where checking / polling continues to report an update * behaviour where checking / polling continues to report an update
* until the topic is read. * until the topic is read.
*/ */
if (sd->update_reported) { if (sd->update_reported()) {
ret = true; ret = true;
break; break;
} }
@@ -467,7 +503,7 @@ uORB::DeviceNode::appears_updated(SubscriberData *sd)
* must have collected the update we reported, otherwise * must have collected the update we reported, otherwise
* update_reported would still be true. * update_reported would still be true.
*/ */
if (!hrt_called(&sd->update_call)) { if (!hrt_called(&sd->update_interval->update_call)) {
break; break;
} }
@@ -476,15 +512,15 @@ uORB::DeviceNode::appears_updated(SubscriberData *sd)
* until the interval has passed once more by restarting the interval * until the interval has passed once more by restarting the interval
* timer and thereby re-scheduling a poll notification at that time. * timer and thereby re-scheduling a poll notification at that time.
*/ */
hrt_call_after(&sd->update_call, hrt_call_after(&sd->update_interval->update_call,
sd->update_interval, sd->update_interval->interval,
&uORB::DeviceNode::update_deferred_trampoline, &uORB::DeviceNode::update_deferred_trampoline,
(void *)this); (void *)this);
/* /*
* Remember that we have told the subscriber that there is data. * Remember that we have told the subscriber that there is data.
*/ */
sd->update_reported = true; sd->set_update_reported(true);
ret = true; ret = true;
break; break;
+15 -5
View File
@@ -183,12 +183,22 @@ protected:
virtual void poll_notify_one(struct pollfd *fds, pollevent_t events); virtual void poll_notify_one(struct pollfd *fds, pollevent_t events);
private: private:
struct SubscriberData { struct UpdateIntervalData {
unsigned generation; /**< last generation the subscriber has seen */ unsigned interval; /**< if nonzero minimum interval between updates */
unsigned update_interval; /**< if nonzero minimum interval between updates */
struct hrt_call update_call; /**< deferred wakeup call if update_period is nonzero */ struct hrt_call update_call; /**< deferred wakeup call if update_period is nonzero */
bool update_reported; /**< true if we have reported the update via poll/check */ };
int priority; /**< priority of publisher */ struct SubscriberData {
~SubscriberData() { if (update_interval) { delete(update_interval); } }
unsigned generation; /**< last generation the subscriber has seen */
int flags; /**< lowest 8 bits: priority of publisher, 9. bit: update_reported bit */
UpdateIntervalData *update_interval; /**< if null, no update interval */
int priority() const { return flags & 0xff; }
void set_priority(uint8_t prio) { flags = (flags & ~0xff) | prio; }
bool update_reported() const { return flags & (1 << 8); }
void set_update_reported(bool update_reported_flag) { flags = (flags & ~(1 << 8)) | (((int)update_reported_flag) << 8); }
}; };
const struct orb_metadata *_meta; /**< object metadata information */ const struct orb_metadata *_meta; /**< object metadata information */
+52 -17
View File
@@ -136,7 +136,7 @@ uORB::DeviceNode::open(device::file_t *filp)
sd->generation = _generation; sd->generation = _generation;
/* set priority */ /* set priority */
sd->priority = _priority; sd->set_priority(_priority);
filp->priv = (void *)sd; filp->priv = (void *)sd;
@@ -169,7 +169,10 @@ uORB::DeviceNode::close(device::file_t *filp)
SubscriberData *sd = filp_to_sd(filp); SubscriberData *sd = filp_to_sd(filp);
if (sd != nullptr) { if (sd != nullptr) {
hrt_cancel(&sd->update_call); if (sd->update_interval) {
hrt_cancel(&sd->update_interval->update_call);
}
remove_internal_subscriber(); remove_internal_subscriber();
delete sd; delete sd;
sd = nullptr; sd = nullptr;
@@ -222,13 +225,13 @@ uORB::DeviceNode::read(device::file_t *filp, char *buffer, size_t buflen)
} }
/* set priority */ /* set priority */
sd->priority = _priority; sd->set_priority(_priority);
/* /*
* Clear the flag that indicates that an update has been reported, as * Clear the flag that indicates that an update has been reported, as
* we have just collected it. * we have just collected it.
*/ */
sd->update_reported = false; sd->set_update_reported(false);
unlock(); unlock();
@@ -306,19 +309,45 @@ uORB::DeviceNode::ioctl(device::file_t *filp, int cmd, unsigned long arg)
unlock(); unlock();
return PX4_OK; return PX4_OK;
case ORBIOCSETINTERVAL: case ORBIOCSETINTERVAL: {
lock(); int ret = PX4_OK;
sd->update_interval = arg; lock();
sd->last_update = hrt_absolute_time();
unlock(); if (arg == 0) {
return PX4_OK; if (sd->update_interval) {
delete(sd->update_interval);
sd->update_interval = nullptr;
}
} else {
if (sd->update_interval) {
sd->update_interval->interval = arg;
sd->update_interval->last_update = hrt_absolute_time();
} else {
sd->update_interval = new UpdateIntervalData();
if (sd->update_interval) {
memset(&sd->update_interval->update_call, 0, sizeof(hrt_call));
sd->update_interval->interval = arg;
sd->update_interval->last_update = hrt_absolute_time();
} else {
ret = -ENOMEM;
}
}
}
unlock();
return ret;
}
case ORBIOCGADVERTISER: case ORBIOCGADVERTISER:
*(uintptr_t *)arg = (uintptr_t)this; *(uintptr_t *)arg = (uintptr_t)this;
return PX4_OK; return PX4_OK;
case ORBIOCGPRIORITY: case ORBIOCGPRIORITY:
*(int *)arg = sd->priority; *(int *)arg = sd->priority();
return PX4_OK; return PX4_OK;
case ORBIOCSETQUEUESIZE: case ORBIOCSETQUEUESIZE:
@@ -327,7 +356,13 @@ uORB::DeviceNode::ioctl(device::file_t *filp, int cmd, unsigned long arg)
return update_queue_size(arg); return update_queue_size(arg);
case ORBIOCGETINTERVAL: case ORBIOCGETINTERVAL:
*(unsigned *)arg = sd->update_interval; if (sd->update_interval) {
*(unsigned *)arg = sd->update_interval->interval;
} else {
*(unsigned *)arg = 0;
}
return OK; return OK;
default: default:
@@ -466,7 +501,7 @@ uORB::DeviceNode::appears_updated(SubscriberData *sd)
/* /*
* Handle non-rate-limited subscribers. * Handle non-rate-limited subscribers.
*/ */
if (sd->update_interval == 0) { if (sd->update_interval == nullptr) {
ret = true; ret = true;
break; break;
} }
@@ -478,22 +513,22 @@ uORB::DeviceNode::appears_updated(SubscriberData *sd)
* behaviour where checking / polling continues to report an update * behaviour where checking / polling continues to report an update
* until the topic is read. * until the topic is read.
*/ */
if (sd->update_reported) { if (sd->update_reported()) {
ret = true; ret = true;
break; break;
} }
// If we have not yet reached the deadline, then assume that we can ignore any // If we have not yet reached the deadline, then assume that we can ignore any
// newly received data. // newly received data.
if (sd->last_update + sd->update_interval > hrt_absolute_time()) { if (sd->update_interval->last_update + sd->update_interval->interval > hrt_absolute_time()) {
break; break;
} }
/* /*
* Remember that we have told the subscriber that there is data. * Remember that we have told the subscriber that there is data.
*/ */
sd->update_reported = true; sd->set_update_reported(true);
sd->last_update = hrt_absolute_time(); sd->update_interval->last_update = hrt_absolute_time();
ret = true; ret = true;
break; break;
+15 -5
View File
@@ -120,13 +120,23 @@ protected:
virtual void poll_notify_one(px4_pollfd_struct_t *fds, pollevent_t events); virtual void poll_notify_one(px4_pollfd_struct_t *fds, pollevent_t events);
private: private:
struct SubscriberData { struct UpdateIntervalData {
unsigned generation; /**< last generation the subscriber has seen */ unsigned interval; /**< if nonzero minimum interval between updates */
unsigned update_interval; /**< if nonzero minimum interval between updates */
uint64_t last_update; /**< time at which the last update was provided, used when update_interval is nonzero */ uint64_t last_update; /**< time at which the last update was provided, used when update_interval is nonzero */
struct hrt_call update_call; /**< deferred wakeup call if update_period is nonzero */ struct hrt_call update_call; /**< deferred wakeup call if update_period is nonzero */
bool update_reported; /**< true if we have reported the update via poll/check */ };
int priority; /**< priority of publisher */ struct SubscriberData {
~SubscriberData() { if (update_interval) { delete(update_interval); } }
unsigned generation; /**< last generation the subscriber has seen */
int flags; /**< lowest 8 bits: priority of publisher, 9. bit: update_reported bit */
UpdateIntervalData *update_interval; /**< if null, no update interval */
int priority() const { return flags & 0xff; }
void set_priority(uint8_t prio) { flags = (flags & ~0xff) | prio; }
bool update_reported() const { return flags & (1 << 8); }
void set_update_reported(bool update_reported_flag) { flags = (flags & ~(1 << 8)) | (((int)update_reported_flag) << 8); }
}; };
const struct orb_metadata *_meta; /**< object metadata information */ const struct orb_metadata *_meta; /**< object metadata information */