int sthread_mutex_lock(sthread_mutex_t *mutex) { sthread_t ptr_this_thread = sthread_self(); //fighting for the right to modify Q while(test_and_set(&mutex->M)){} //after this I am now the only one //to modify the passed in mutex //therefore I should go ahead and //modify the lock and Q if needed //check if I should go into critical //section struct queue *pQ = &mutex->Q; if(Q_empty(pQ)) { //lock available Q_push(pQ, ptr_this_thread); mutex->M = 0; // I am done with Q; others can come and look / change Q. return 0; //this_thread will go into critical section } else { //lock not available //there are someone or myself before me in the Q //if it is myself in criticle section //I shoud not wait for myself to wake myself up //I will increment counter and keep running in criticle seciton //else //someone else is before me in the Q //either he is sleeping (he is not the 1st) //or he is in the critical section now (he is the 1st and //I am the 2nd in Q) //either way I should go to bed and wait for him to wake me up if(Q_first(pQ)->ptr_thread == ptr_this_thread) { Q_first(pQ)->count++; //Trying to acquire the lock own by myself //take down this attempt and keep myself in //criticle section mutex->M = 0; //I am done with lock; others can now check / modify lock. } else { Q_push(pQ, ptr_this_thread); mutex->M = 0; sthread_suspend(); //Other thread is in criticle section //I should go to bed and sleep return 0; //the moment I am woken up will //return 0 to caller } } }
struct q_member * Q_pop(struct queue *pQ) { if(Q_empty(pQ)) //instant fail return NULL; else { pQ->size--; struct q_member * p_first = Q_first(pQ); pQ->head = (pQ->head + 1 % MAX_Q_SIZE); return p_first; } }
int sthread_mutex_trylock(sthread_mutex_t *mutex) { sthread_t ptr_this_thread = sthread_self(); //fighting for the right to modify Q while(test_and_set(&mutex->M)){} //after this I am now the only one //to modify the passed in mutex //therefore I should go ahead and //modify the lock and Q if needed //check if I should go into critical //section struct queue *pQ = &mutex->Q; if(Q_empty(pQ)) { //lock available Q_push(pQ, ptr_this_thread); mutex->M = 0; // I am done with Q; others can come and look / change Q. //this_thread will go into critical section return 0; } else { //lock not available if(Q_first(pQ)->ptr_thread == ptr_this_thread) { Q_first(pQ)->count++;//Trying to acquire the lock own by myself //take down this attempt and keep myself in //criticle section mutex->M = 0; //I am done with lock; others can now check / modify lock. } //do not block caller //return non-zero indication lock not available return -1; } }
int sthread_mutex_unlock(sthread_mutex_t *mutex) { //fighting for the right to modify Q while(test_and_set(&mutex->M) == 1){} //I am the only one checking mutex //can modify Q struct queue *pQ = &mutex->Q; if(Q_first(pQ)->count == 1) { Q_pop(pQ); if(Q_empty(pQ) == 0) { //Queue is not empty //there are other threads sleeping //int the Q sthread_wake(Q_first(pQ)->ptr_thread); } else { //I am the last one int the Q //Do nothing } return 0; } else if( Q_first(pQ)->count > 1) { //I have acquired the lock owned by me //more than once need to unlock Q_first(pQ)->count--; } else { // printf("Bad!! count is 0 or less\n"); return -1; } }
// // Add the points two the two initial triangles of a Tin tile from // file. Also add points from neighbor boundary arrays to the // triangulation to have boundary consistancy // TIN_TILE *initTilePoints(TIN_TILE *tt, double e, short useNodata){ // First two tris TRIANGLE *first = tt->t; TRIANGLE *second = tt->t->p1p3; // Get back to the beginning of the tile data file rewind(tt->gridFile); // Now build list of points in the triangle // Create a dummy tail for both point lists first->points = Q_init(); second->points = Q_init(); first->maxE = DONE; second->maxE = DONE; // Build the two point lists register int row, col; ELEV_TYPE maxE_first=0; ELEV_TYPE maxE_second=0; ELEV_TYPE tempE = 0; R_POINT temp; // iterate through all points and distribute them to the // two triangles for(row=0;row<tt->nrows;row++) { temp.x=row+tt->iOffset; for(col=0;col<tt->ncols;col++) { temp.y=col+tt->jOffset; fread(&temp.z,sizeof(ELEV_TYPE), 1, tt->gridFile); // Only set Z values for corner points since they already exist if(row==0 && col==0){ tt->nw->z = temp.z; continue; } if(row==0 && col==tt->ncols-1){ tt->ne->z = temp.z; continue; } if(row==tt->nrows-1 && col==tt->ncols-1){ tt->se->z = temp.z; continue; } if(row==tt->nrows-1 && col==0){ tt->sw->z = temp.z; continue; } //Ignore edge points if internal tile if(tt->iOffset != 0 && row == 0) continue; if(tt->jOffset != 0 && col == 0) continue; //Skip nodata or change it to min-1 if(temp.z == tt->nodata){ if(!useNodata) continue; else temp.z = tt->min-1; } // Add to the first triangle's list if(inTri2D(first->p1, first->p2, first->p3, &temp)) { Q_insert_elem_head(first->points, temp); //Update max error tempE = findError(temp.x,temp.y,temp.z,first); if (tempE > maxE_first) { maxE_first = tempE; assert(Q_first(first->points)); // store pointer to triangle w/ max err first->maxE = &Q_first(first->points)->e; first->maxErrorValue = tempE; } } // Add to the second triangle's list else { assert(inTri2D(second->p1, second->p2, second->p3, &temp)); Q_insert_elem_head(second->points, temp); //Update max error tempE = findError(temp.x,temp.y,temp.z,second); if (tempE > maxE_second) { maxE_second = tempE; assert(Q_first(second->points)); // store pointer to triangle w/ max err second->maxE = &Q_first(second->points)->e; second->maxErrorValue = tempE; } } }//for col }//for row //end distribute points among initial triangles DEBUG {checkPointList(first); checkPointList(second);} // First triangle has no points with error > e, mark as done if (first->maxE == DONE){ Q_free_queue(first->points); first->points = NULL; first->maxErrorValue = 0; } // Insert max error point into the PQ else PQ_insert(tt->pq,first); // Second triangle has no points with error > e, mark as done if (second->maxE == DONE){ Q_free_queue(second->points); second->points = NULL; second->maxErrorValue = 0; } // Insert max error point into the PQ else PQ_insert(tt->pq,second); // Initialize point pointer arrays // At most points can have (tl*tl)-2*tl points in it // At most bPoints and rPoints can have tl points tt->points = (R_POINT **)malloc( ((tt->nrows * tt->ncols) - (tt->nrows + tt->ncols)) * sizeof(R_POINT*)); tt->bPoints = (R_POINT **)malloc( tt->ncols * sizeof(R_POINT*)); tt->rPoints = (R_POINT **)malloc( tt->nrows * sizeof(R_POINT*)); // Add points to point pointer array tt->points[0]=tt->nw;//nw tt->bPoints[0]=tt->sw;//sw tt->bPoints[1]=tt->se;//se tt->rPoints[0]=tt->ne;//ne tt->rPoints[1]=tt->se;//se tt->pointsCount = 1; tt->bPointsCount = 2; tt->rPointsCount = 2; // // Add boundary points to the triangulation // int i; COORD_TYPE prevX = 0,prevY = 0; TRIANGLE *t1,*t2, *s, *sp; s = tt->t; sp = tt->t->p1p3; if(tt->left != NULL){ // The first & last point in this array are corner points for this // tile so we ignore them for(i = 1; i < tt->left->rPointsCount-1; i++){ assert(s && tt->pq && tt->left->rPoints[i]); assert(prevX <= tt->left->rPoints[i]->x && prevY <= tt->left->rPoints[i]->y); assert(tt->left->rPoints[i] != tt->nw && tt->left->rPoints[i] != tt->ne && tt->left->rPoints[i] != tt->sw && tt->left->rPoints[i] != tt->se); // add 2 tris in s t1 = addTri(tt, s->p1, tt->left->rPoints[i], s->p3, NULL,whichTri(s,s->p1,s->p3,tt),NULL); assert(t1); t2 = addTri(tt, tt->left->rPoints[i], s->p2, s->p3, NULL,t1,whichTri(s,s->p2,s->p3,tt)); assert(t2); // Verify that t1 and t2 are really inside s triangleCheck(s,t1,t2,NULL); // Distribute points in the 2 triangles if(s->maxE != DONE){ s->p1p2 = s->p1p3 = s->p2p3 = NULL; distrPoints(t1,t2,NULL,s,NULL,e,tt); //Mark triangle s for deletion from pq before distrpoints so we //can include its maxE in the newly created triangle PQ_delete(tt->pq,s->pqIndex); } else{ // Since distrpoints normally fixes corner we need to do it here if(s == tt->t){ updateTinTileCorner(tt,t1,t2,NULL); } t1->maxE = t2->maxE = DONE; t1->points = t2->points = NULL; } removeTri(s); tt->numTris++; tt->numPoints++; // Now split the next lowest boundary triangle s = t2; // Should we enforce Delaunay here? prevX = tt->left->rPoints[i]->x; prevY = tt->left->rPoints[i]->y; } } if(tt->top != NULL){ // The first & last point in this array are corner points for this // tile so we ignore them s = sp; prevX = prevY = 0; for(i = 1; i < tt->top->bPointsCount-1; i++){ assert(s && tt->pq && tt->top->bPoints[i]); assert(prevX <= tt->top->bPoints[i]->x && prevY <= tt->top->bPoints[i]->y); // add 2 tris in s t1 = addTri(tt, s->p1, tt->top->bPoints[i], s->p3, NULL,whichTri(s,s->p1,s->p3,tt),NULL); assert(t1); t2 = addTri(tt, tt->top->bPoints[i], s->p2, s->p3, NULL,t1,whichTri(s,s->p2,s->p3,tt)); assert(t2); // Verify that t1 and t2 are really inside s triangleCheck(s,t1,t2,NULL); // Distribute points in the 2 triangles if(s->maxE != DONE){ distrPoints(t1,t2,NULL,s,NULL,e,tt); //Mark triangle sp for deletion from pq before distrpoints so we //can include its maxE in the newly created triangle s->p1p2 = s->p1p3 = s->p2p3 = NULL; PQ_delete(tt->pq,s->pqIndex); } else{ // Since distrpoints normally fixes corner we need to do it here if(s == tt->t){ updateTinTileCorner(tt,t1,t2,NULL); } t1->maxE = t2->maxE = DONE; t1->points = t2->points = NULL; } removeTri(s); tt->numTris++; tt->numPoints++; // Now split the next lowest boundary triangle s = t2; // Should we enforce Delaunay here? prevX = tt->top->bPoints[i]->x; prevY = tt->top->bPoints[i]->y; } } return tt; }