- list_for_each_entry_safe(loop_msg, tmp_msg, &exec_list, list) {
- msg = running_with_devpath(loop_msg);
- if (!msg) {
- /* move event to run list */
- list_move_tail(&loop_msg->list, &running_list);
- udev_run(loop_msg);
- dbg("moved seq %d to running list", loop_msg->seqnum);
- } else {
- dbg("delay seq %d, cause seq %d already working on '%s'",
- loop_msg->seqnum, msg->seqnum, msg->devpath);
+ snprintf(procdir, sizeof(procdir), "/proc/%s/stat", dent->d_name);
+ procdir[sizeof(procdir)-1] = '\0';
+
+ f = open(procdir, O_RDONLY);
+ if (f == -1)
+ continue;
+
+ len = read(f, line, sizeof(line)-1);
+ close(f);
+
+ if (len <= 0)
+ continue;
+ else
+ line[len] = '\0';
+
+ /* skip ugly program name */
+ pos = strrchr(line, ')') + 2;
+ if (pos == NULL)
+ continue;
+
+ if (sscanf(pos, "%c %d %d %d ", &state, &ppid, &pgrp, &sess) != 4)
+ continue;
+
+ /* count only processes in our session */
+ if (sess != session)
+ continue;
+
+ /* count only running, no sleeping processes */
+ if (state != 'R')
+ continue;
+
+ running++;
+ if (limit > 0 && running >= limit)
+ break;
+ }
+ closedir(dir);
+
+ return running;
+}
+
+static int compare_devpath(const char *running, const char *waiting)
+{
+ int i;
+
+ for (i = 0; i < PATH_SIZE; i++) {
+ /* identical device event found */
+ if (running[i] == '\0' && waiting[i] == '\0')
+ return 1;
+
+ /* parent device event found */
+ if (running[i] == '\0' && waiting[i] == '/')
+ return 2;
+
+ /* child device event found */
+ if (running[i] == '/' && waiting[i] == '\0')
+ return 3;
+
+ /* no matching event */
+ if (running[i] != waiting[i])
+ break;
+ }
+
+ return 0;
+}
+
+/* returns still running task for the same device, its parent or its physical device */
+static int running_with_devpath(struct uevent_msg *msg, int limit)
+{
+ struct uevent_msg *loop_msg;
+ int childs_count = 0;
+
+ if (msg->devpath == NULL)
+ return 0;
+
+ /* skip any events with a timeout set */
+ if (msg->timeout != 0)
+ return 0;
+
+ list_for_each_entry(loop_msg, &running_list, node) {
+ if (limit && childs_count++ > limit) {
+ dbg("%llu, maximum number (%i) of child reached", msg->seqnum, childs_count);
+ return 1;
+ }
+ if (loop_msg->devpath == NULL)
+ continue;
+
+ /* return running parent/child device event */
+ if (compare_devpath(loop_msg->devpath, msg->devpath) != 0) {
+ dbg("%llu, child device event still running %llu (%s)",
+ msg->seqnum, loop_msg->seqnum, loop_msg->devpath);
+ return 2;