void UmlActivityAction::write_end(FileOut & out, bool dontclose) { out << ">\n"; out.indent(+1); Q3CString s = constraint(); if (! s.isEmpty()) { out.indent(); out << "<ownedRule xmi:type=\"uml:Constraint\""; out.id_prefix(this, "CONSTRAINT_"); out.ref(this, "constrainedElement"); out << ">\n"; out.indent(); out << "\t<specification xmi:type=\"uml:OpaqueExpression\""; out.id_prefix(this, "CSPEC_"); out << ">\n"; out.indent(); out << "\t\t<body>"; out.quote(s); out << "</body>\n"; out.indent(); out << "\t</specification>\n"; out.indent(); out << "</ownedRule>\n"; } write_description_properties(out); switch (_lang) { case Uml: write_condition(out, preCondition(), TRUE); write_condition(out, postCondition(), FALSE); break; case Cpp: write_condition(out, cppPreCondition(), TRUE); write_condition(out, cppPostCondition(), FALSE); break; default: // java write_condition(out, javaPreCondition(), TRUE); write_condition(out, javaPostCondition(), FALSE); } const Q3PtrVector<UmlItem> ch = children(); unsigned n = ch.size(); for (unsigned i = 0; i != n; i += 1) ch[i]->write(out); write_incoming_flows(out); if (!dontclose) write_close(out); }
/* * osprd_ioctl(inode, filp, cmd, arg) * Called to perform an ioctl on the named file. */ int osprd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { osprd_info_t *d = file2osprd(filp); // device info int r = 0; // return value: initially 0 // is file open for writing? int filp_writable = (filp->f_mode & FMODE_WRITE) != 0; // This line avoids compiler warnings; you may remove it. (void) filp_writable, (void) d; // Set 'r' to the ioctl's return value: 0 on success, negative on error if (cmd == OSPRDIOCACQUIRE) { // EXERCISE: Lock the ramdisk. // // If *filp is open for writing (filp_writable), then attempt // to write-lock the ramdisk; otherwise attempt to read-lock // the ramdisk. // // This lock request must block using 'd->blockq' until: // 1) no other process holds a write lock; // 2) either the request is for a read lock, or no other process // holds a read lock; and // 3) lock requests should be serviced in order, so no process // that blocked earlier is still blocked waiting for the // lock. // // If a process acquires a lock, mark this fact by setting // 'filp->f_flags |= F_OSPRD_LOCKED'. You also need to // keep track of how many read and write locks are held: // change the 'osprd_info_t' structure to do this. // // Also wake up processes waiting on 'd->blockq' as needed. // // If the lock request would cause a deadlock, return -EDEADLK. // If the lock request blocks and is awoken by a signal, then // return -ERESTARTSYS. // Otherwise, if we can grant the lock request, return 0. // 'd->ticket_head' and 'd->ticket_tail' should help you // service lock requests in order. These implement a ticket // order: 'ticket_tail' is the next ticket, and 'ticket_head' // is the ticket currently being served. You should set a local // variable to 'd->ticket_head' and increment 'd->ticket_head'. // Then, block at least until 'd->ticket_tail == local_ticket'. // (Some of these operations are in a critical section and must // be protected by a spinlock; which ones?) // Your code here (instead of the next two lines). int my_ticket = 0; ///keep track of my ticket osp_spin_lock(&d->mutex); my_ticket = d->ticket_head++; osp_spin_unlock(&d->mutex); d->pid_tracker[my_ticket%MAX_MEM_SIZE] = current->pid; #ifdef DEBUG eprintk("Handling ACQUIRE, my_ticket is %d\n",my_ticket); eprintk("Current pid is :%d\n", current->pid); #endif //check self deadlock osp_spin_lock(&d->mutex); int run_count = d->read_count + d->write_count; int index = (d->ticket_tail - 1)%MAX_MEM_SIZE; osp_spin_unlock(&d->mutex); while(run_count > 0) { if(d->pid_tracker[index] == current->pid) return -EDEADLK; index--; if(index<0) index = MAX_MEM_SIZE - 1; run_count--; } //check loop deadlock if(filp_writable) { wait_event_interruptible(d->blockq, d->write_count == 0 && d->read_count == 0 && d->ticket_tail >= my_ticket); osp_spin_lock(&d->mutex); d->write_count++; d->ticket_tail++; filp->f_flags |= F_OSPRD_LOCKED; osp_spin_unlock(&d->mutex); } else { wait_event_interruptible(d->blockq, d->write_count == 0 && d->ticket_tail >= my_ticket); osp_spin_lock(&d->mutex); d->ticket_tail++; d->read_count++; filp->f_flags |= F_OSPRD_LOCKED; osp_spin_unlock(&d->mutex); } r=0; /* eprintk("Attempting to acquire\n"); r = -ENOTTY; */ } else if (cmd == OSPRDIOCTRYACQUIRE) { // EXERCISE: ATTEMPT to lock the ramdisk. // // This is just like OSPRDIOCACQUIRE, except it should never // block. If OSPRDIOCACQUIRE would block or return deadlock, // OSPRDIOCTRYACQUIRE should return -EBUSY. // Otherwise, if we can grant the lock request, return 0. // Your code here (instead of the next two lines). #ifdef DEBUG eprintk("Handling TRY ACQUIRE\n"); #endif if(filp_writable) { osp_spin_lock(&d->mutex); if(write_condition(d)) { d->write_count++; filp->f_flags |= F_OSPRD_LOCKED; osp_spin_unlock(&d->mutex); } else { osp_spin_unlock(&d->mutex); return -EBUSY; } } else { osp_spin_lock(&d->mutex); if(read_condition(d)) { d->read_count++; filp->f_flags |= F_OSPRD_LOCKED; osp_spin_unlock(&d->mutex); } else { osp_spin_unlock(&d->mutex); return -EBUSY; } } r = 0; /* eprintk("Attempting to try acquire\n"); r = -ENOTTY; */ } else if (cmd == OSPRDIOCRELEASE) { // EXERCISE: Unlock the ramdisk. // // If the file hasn't locked the ramdisk, return -EINVAL. // Otherwise, clear the lock from filp->f_flags, wake up // the wait queue, perform any additional accounting steps // you need, and return 0. // Your code here (instead of the next line). //r = -ENOTTY; #ifdef DEBUG eprintk("Handling RELEASE\n"); #endif if(filp->f_flags != F_OSPRD_LOCKED) return -EINVAL; //No lock on the ramdisk //check whether current process owns a lock osp_spin_lock(&d->mutex); int showup = 0; int run_count = d->read_count + d->write_count; int index = (d->ticket_tail - 1)%MAX_MEM_SIZE; osp_spin_unlock(&d->mutex); while(run_count > 0) { if(d->pid_tracker[index] == current->pid) { showup = 1; break; } index--; if(index<0) index = MAX_MEM_SIZE - 1; run_count--; } if(showup == 0) return -EINVAL;//current process don't own the lock osp_spin_lock(&d->mutex); filp->f_flags = 0; //reset the flag? if(filp_writable) { d->write_count--; } else { d->read_count--; } wake_up_all(&d->blockq); //Wake up request that holds the next ticket osp_spin_unlock(&d->mutex); r = 0; } else r = -ENOTTY; /* unknown command */ return r; }