I'm trying to understand the Eisenberg-McGuire algorithm and I found this program which implements it but when I run the program I get a segmentation fault.
Segmentation fault: 11
Here is the program
/* Eisenberg-McGuire algorithm: a software approach to N-process
mutual exclusion.
For description of Eisenberg-McGuire algorithm, see page 261 of
"Concurrent Systems - Operating Systems, Database and Distributed
Systems: An Inegrated Approach / Jean Bacon -- 2nd Edition".
Copyrigh (c) 2001 Xiao Zhang */
#include <stdlib.h>
#include <pthread.h>
#include <iostream>
using namespace std;
/**********************************************************************/
/* Eisenberg-McGuire's algorithm for N-process mutual exclusion */
/**********************************************************************/
class eis_mcg_mutex_t {
private:
int n;
enum procphase { out_cr, want_cr, claim_cr } *procphase;
int turn;
public:
/* Initialize the mutex data shared by N processes */
eis_mcg_mutex_t(int nproc)
{
n = nproc;
procphase = new enum procphase [n];
srand(time(0));
turn = (int) (1.0 * n * rand() / (RAND_MAX + 1.0));
for (int i = 0; i < n; i++)
procphase[i] = out_cr;
}
/* Entry protocol for process i */
void mutex_lock(int i) {
procphase[i] = want_cr;
int j = turn;
do
{
while (j != i)
{
if (procphase[j] == out_cr)
j = (j + 1) % n;
else
j = turn;
}
procphase[i] = claim_cr;
j = (j + 1) % n;
while (procphase[j] != claim_cr)
j = (j + 1) % n;
} while (!(j == i && (turn == i || procphase[turn] == out_cr)));
turn = i;
}
/* Exit protocol for process i */
void mutex_unlock(int i)
{
int j = (turn + 1) % n;
while (procphase[j] == out_cr)
j = (j + 1) % n;
turn = j;
procphase[i] = out_cr;
}
};
/**********************************************************************/
/* To test the Eisenberg-McGuire's algorithm, we write a simple */
/* program that creates N threads (processes) and then has each */
/* thread increment a global variable `counter' NLOOP times. The */
/* final value of `counter' is expected to be N * NLOOP. */
/**********************************************************************/
#define N 4 /* number of threads */
#define NLOOP 1000 /* number of times each thread loops */
int counter; /* this is cremented by the threads */
eis_mcg_mutex_t counter_in_use(N);
void *doit(void *arg)
{
int i, val;
int tid = *(int *)arg;
/* Each thread fetches, prints and increments the counter NLOOP times.
The value of the counter should increase monotonically. */
for (i = 0; i < NLOOP; i++) {
/* Replace pthread_mutex_lock() with Eisenberg-McGuire's
enter-critical-section procedure. */
counter_in_use.mutex_lock(tid);
/* Here is critical section */
val = counter;
counter = val + 1;
cout << tid << ": " << counter << endl;
/* Replace pthread_mutex_unlock() with Eisenberg-McGuire's
leave-critical-section procedure. */
counter_in_use.mutex_unlock(tid);
}
return NULL;
}
int main()
{
pthread_t tid[N];
int i;
for (i = 0; i < N; i++) pthread_create(&tid[i], NULL, doit, (void *)i);
for (i = 0; i < N; i++) pthread_join(tid[i], NULL);
return 0;
}
I can't understand what is causing the segmentation fault. Any help is appreciated. Thank You.
Fixed it.
for (i = 0; i < N; i++) pthread_create(&tid[i], NULL, doit, (void *)i);
should be
for (i = 0; i < N; i++) pthread_create(&tid[i], NULL, doit, (void *)&i);
missed the amperson operator for address.
Update:
I didn't pass the address now.
for (i = 0; i < N; i++) pthread_create(&tid[i], NULL, doit, (void *)i);
and in int doit(void *arg), changed int tid = *((int*)(&arg));
It works perfectly now.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I am working on a project about multithreading. Here Operation is a class which contains a type, a key, a time and an answer.
Here is my code:
#include <cstdlib>
#include <fstream>
#include <string>
#include <iomanip>
#include <pthread.h>
#include <vector>
#include "block.h"
using namespace std;
std::vector<Operation> *data;
block_bloom_filter filter(10000000, 0.01);
int ans[30000000];
void *test(void *arg)
{
int thread_id = *((int *)arg);
for (auto &op : data[thread_id])
{
if (op.type == 1)
{
filter.insert(op);
}
else
{
filter.query(op);
}
}
return 0;
}
int main(int argc, char **argv)
{
int k = atoi(argv[1]);
int *op_num = new int[k];
data = new vector<Operation>[k];
for (int i = 0; i < k; i++)
{
string tmp = "data" + to_string(i + 1) + ".in";
const char *s = tmp.c_str();
ifstream fin;
fin.open(s);
fin >> op_num[i];
//data[i] = new Operation[op_num[i]];
for (int j = 0; j < op_num[i]; j++)
{
string tmp1;
fin >> tmp1;
if (tmp1 == "insert")
{
Operation tmp2;
tmp2.type = 1;
fin >> tmp2.key >> tmp2.time;
tmp2.ans = -1;
data[i].push_back(tmp2);
}
else
{
Operation tmp2;
tmp2.type = 2;
fin >> tmp2.key >> tmp2.time;
tmp2.ans = -1;
data[i].push_back(tmp2);
}
}
fin.close();
}
auto start = std::chrono::high_resolution_clock::now();
int num_threads = k;
pthread_t *threads = new pthread_t[num_threads];
//auto **threads = new thread *[num_threads];
//pthread_t *threads = new pthread_t[k];
/*for (int i = 0; i < num_threads; i++)
{
threads[i] = new thread(test, i);
}
for (int i = 0; i < num_threads; i++)
{
threads[i]->join();
}*/
for (int i = 0; i < k; i++)
{
pthread_create(&threads[i], NULL, test, (void *)&(i));
}
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
//std::cerr << "duration = " << duration.count() << "us" << std::endl;
double time_used = duration.count() / 1e3;
std::ofstream f_time("time.out");
f_time << std::fixed << std::setprecision(3) << time_used << std::endl;
f_time.close();
for (int i = 0; i < k; i++)
{
for (int j = 0; j < op_num[i]; j++)
{
ans[data[i][j].time - 1] = data[i][j].ans;
}
}
ofstream fout;
fout.open("result.out");
for (int i = 0; i < 30000000; i++)
{
if (ans[i] >= 0)
fout << ans[i] << endl;
}
fout.close();
delete[] data;
delete[] threads;
delete[] op_num;
//pthread_exit(NULL);
}
My code can compile, but when running it shows segmentation fault and can only generate time.out no result.out. I've been working on it for a long time but still do not know why. Hope someone can help me.
Below is block.h
#include <algorithm>
#include <chrono>
#include <cmath>
#include <ctime>
#include <fstream>
#include <iostream>
#include <numeric>
#include <string>
#include <vector>
#include "Headers/MurmurHash3.h"
#include "xxHash/xxhash.c"
#define M_LN2 0.69314718055994530942
using namespace std;
typedef std::vector<bool> bit_vector;
class Operation
{
public:
int type; // 1: insert, 2: query
char key[17];
int time;
int ans;
};
int str_len = 16;
int cache_size = 64;
int block_size = 512;
int key_num = 10000000;
int slot_num = 1 << 27;
int hash_num = int((double)slot_num / key_num * M_LN2);
int block_num = (slot_num + block_size - 1) / block_size;
class bloom_filter
{
uint32_t size; // Probable Number of elements in universe
double fpr; // False positive rate
int m; // optimal size of bloom filter
int k; // Number of hash functions
bit_vector bloom;
public:
int get_size() { return size; }
double get_fpr() { return fpr; }
bloom_filter(int n, double fpr)
{
this->size = n;
this->fpr = fpr;
this->m = ceil(
-((n * log(fpr)) /
pow(log(2), 2.0))); // Natural logarithm m = −n ln p/(ln 2)2
// cout << m<< "\n";
this->k = ceil(
(m / n) * log(2)); // Calculate k k = (m/n) ln 2 2-k ≈ 0.6185 m/n
// cout << k;
bloom.resize(m, false);
}
void insert(string S)
{
uint32_t *p = new uint32_t(1); // For storing Hash Vaue
const void *str = S.c_str(); // Convert string to C string to use as a
// parameter for constant void
int index;
// cout<<S.length()<<"\t"<<sizeof(str)<<"\n";
// cout<<S<<"\n";
for (int i = 0; i < k; i++)
{
// MurmurHash3_x64_128();
MurmurHash3_x86_32(str, S.length(), i + 1,
p); // String, String size
index = *p % m;
// cout<<*p<<"\t"<<index<<"\t";
bloom[index] = true;
}
// cout<<"\n";
// print();
}
/*void print()
{
for (int i = 0; i < bloom.size(); i++)
{
cout << bloom.at(i);
}
}*/
char query(string S)
{
uint32_t *p = new uint32_t(1); // For storing Hash Vaue
const void *str = S.c_str(); // Convert string to C string to use as a
// parameter for constant void
int index;
// cout << S.length() << "\t" << sizeof(str) << "\n";
// cout<<S<<"\n";
for (int i = 0; i < k; i++)
{
// MurmurHash3_x64_128();
MurmurHash3_x86_32(str, S.length(), i + 1,
p); // String, String size
index = *p % m;
// cout<<*p<<"\t"<<index<<"\t";
if (bloom[index] == false)
return 'N';
}
return 'Y';
}
};
class block_bloom_filter
{
int size; // Probable Number of elements in universe
double fpr; // False positive rate
int m; // optimal size of bloom filter
int k; // Number of hash functions
int s; // Number of bloom filters
bit_vector block_bloom;
int cache_line_size;
public:
int get_size() { return size; }
double get_fpr() { return fpr; }
block_bloom_filter(int n, double fpr)
{
this->size = n;
this->fpr = fpr;
this->m = ceil(
-((n * log(fpr)) /
pow(log(2), 2.0))); // Natural logarithm m = −n ln p/(ln 2)2
// cout << m << "\n";
this->k = ceil(
(m / n) * log(2)); // Calculate k k = (m/n) ln 2 2-k ≈ 0.6185 m/n
// cout << k<<"\n";
this->cache_line_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE) * 8;
this->s =
ceil((double)m / cache_line_size); // Total number of Bloom Filters
// cout<<s<<"s valye\n";
block_bloom.resize(cache_line_size * s, false);
}
/*void insert(Operation &S)
{
int block_number;
int first_index, last_index;
int index;
uint32_t *p = new uint32_t(1); // For storing Hash Value
const void *str = S.key.c_str(); // Convert string to C string to use as a
// parameter for constant void
MurmurHash3_x86_32(str, sizeof(str), 1,
p); // String, String size//Find out block number
// if(s!=0)
block_number = *p % s;
first_index = block_number * cache_line_size;
for (int i = 1; i < k; i++)
{
// MurmurHash3_x64_128();
MurmurHash3_x86_32(str, S.key.length(), i + 1,
p); // String, String size
// cout<<*p<<"\n";
// cout<<"div="<<div << "\n";
index = (*p) % cache_line_size;
// cout<<index<<"\t";
// if(index>m) cout<<"\n"<<index<<"\tError detected\n";
// cout<<"\n"<<index<<"a\t\n";
// cout<<"\n"<<first_index<<"a\t\n";
// cout<<(index+first_index)<<"a\t\n";
block_bloom[index + first_index] = true;
}
// cout<<"\n";
// print();
}*/
XXH64_hash_t GetHash(const char *str)
{
return XXH3_64bits_withSeed(str, 16, /* Seed */ 123976235672331983ll);
}
void insert(Operation &s)
{
XXH64_hash_t hash = GetHash(s.key);
XXH64_hash_t hash1 = hash % m;
XXH64_hash_t hash2 = (hash / m) % m;
for (int i = 0; i < k; i++)
{
int pos = (hash1 + i * hash2) % m;
block_bloom[pos] = 1;
}
}
void query(Operation &s)
{
XXH64_hash_t hash = GetHash(s.key);
XXH64_hash_t hash1 = hash % m;
XXH64_hash_t hash2 = (hash / m) % m;
for (int i = 0; i < k; i++)
{
int pos = (hash1 + i * hash2) % m;
if (!block_bloom[pos])
{
s.ans = 0;
return;
}
}
s.ans = 1;
return;
}
};
for (int i = 0; i < k; i++)
{
pthread_create(&threads[i], NULL, test, (void *)&(i));
The third parameter to pthread_create(), the thread function's parameter, is a pointer to the loop variable. The thread function reads it, as follows:
void *test(void *arg)
{
int thread_id = *((int *)arg);
There are no guarantees whatsoever that this gets executed by the new execution thread before the parent execution thread increments i. When it comes to multiple execution threads, neither POSIX nor the C++ library gives you any guarantees as to the relative execution order of multiple threads.
All that pthread_create() guarantees you is that at some point in time later, which can before before or after pthread_create() returns, the new execution thread pops into existence and begins executing the thread function.
And it may very well be that one or more (if not all) execution threads finally begin executing, for real, after the for loop terminates and i gets destroyed. At which pointL when they do start executing, they will discover a pointer to a destroyed variable as their argument, and dereferencing it becomes undefined behavior.
Or, some of those execution threads get their gear running, at some point after they get created. By this time i's been incremented a couple of times already. So they both read the *(int *)arg, whose value is now -- who knows? And, just to make things interesting, both execution threads do this at the same time, and read the same value. At this point, the end result is already going to be garbage. It is clear that the intent here is for each execution thread getting a unique value for its parameter, but this very unlikely to happen here. There's nothing in the shown code that ensures that each execution threads actually gets its own unique thread_id.
Additionally, the original parent execution thread seems to assume that all the execution threads will all finish their job before the parent execution thread reads their results, and writes them out to a file.
Unfortunately, there's no code in the parent execution thread that appears to actually wait for all execution threads to finish. As soon as they're all started, it takes it on faith that they complete instantly, and it reads the partial results, and writes it out to a file:
auto stop = std::chrono::high_resolution_clock::now();
Well, the bad news here is that there's nothing that actually waits for all execution threads to actually stop, at this point. They're still running here. Even if the program manages to avoid crashing, the output results will be incomplete, and mostly junk.
ans[data[i][j].time - 1]
It appears that the value of .time here was originally read from the input file. There does not appear to be any bounds checking here. It's possible for this vector/array access to be out of bounds, resulting in an undefined behavior and a likely crash.
Also, another problem with the shown code: There are plenty of calls to new, but only some of those get deleted, resulting in multiple memory leaks. Inspecting the shown code, there is no clear reason to new anything, in the first place.
In conclusion, there are multiple problems with the shown code that result in undefined behavior, and any of them will be the reason for the observed crash. The shown approach is very much error-prone, and will require much more substantial work, and proper multi-threading support, and inter-thread sequencing, in order to get the sequence of all events happen in the correct order, across all the execution threads.
I'm writing a program for my algorithmic math class at university and I'm using Win 7 (x64), Eclipse Oxygen.1a Release (4.7.1a) with MinGW 6.3.0.
Whenever I build and run the program it crashes with windows claiming 'Abgabe3.exe stopped working' but when trying to find the problem using the debugger and breakpoints I step trough the whole program and it finishes without errors...
I stripped everything not used by the problematic function and copied everything into a seperate file and the exact problem occurs.
Maybe somebody has a clue what happened at my side. ^^
#include <math.h> /* pow, sqrt */
#include <iostream> /* cin, cout */
#include <new> /* new */
#include <string> /* string */
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
using namespace std;
void NORM(double* res, double* x, int n){
res[0] = 0.0;
for(int i = 0; i < n; i++){
res[0] += pow(x[i], 2);
}
res[0] = sqrt(res[0]);
}
void initRand(double* x, int n){
srand (time(NULL) * rand());
for(int i = 0; i < n; i++){
x[i] = (((double) rand()) / ((double) RAND_MAX));
}
}
void createArray(double* &x, int n){
if (n > 0){
x = new double[n];
initRand(x, n);
}
}
void printArray(double* x, int n){
if (x != NULL){
cout<<"(\n";
for(int i = 0; i < n; i++){
if(i+1 == n) cout<<x[i];
else if ((i % 5) == 0) cout<<x[i];
else if ( ((i+1) % 5) == 0 ){
cout<<", "<<x[i]<<"\n";
}
else {
cout<<", "<<x[i];
}
}
cout<<"\n)\n";
}
else cout<<"\nError: pointer = NULL\n";
}
unsigned long long int bin(unsigned int n, unsigned int k){
unsigned long long res = 1;
if(k == 0) return 1;
else if( n >= k){
for(unsigned long long int i = 1; i <= k; i++){
res *= (n + 1 - i) / i;
}
}
else return 0;
return res;
}
void newArray(double** x, unsigned int v, unsigned int n){
for(unsigned int i = 0; i < v; i++){
double* ptr = x[i];
createArray(ptr,n);
x[i] = ptr;
}
}
void experiment(double** vektorArray){
unsigned int n = 10, v = 20;
cout<<"Dimension n = "<<n<<"\nAnzahl Versuche v = "<<v<<endl;
//Erstellen der Vektoren
cout<<"Erstellen - starte\n";
vektorArray = new double*[n];
newArray(vektorArray, v, n);
cout<<"Erstellen - fertig\n";
for(unsigned int i = 0; i < v; i++){
if(i%10 == 0) printArray(vektorArray[i], n);
}
}
int main(int argc, char** argv){
double** vektorArray = NULL;
experiment(vektorArray);
return 0;
}
vektorArray = new double*[n];
created an array of size n, but
void newArray(double** x, unsigned int v, unsigned int n)
{
for (unsigned int i = 0; i < v; i++)
{
double* ptr = x[i];
createArray(ptr, n);
x[i] = ptr;
}
}
and
for (unsigned int i = 0; i < v; i++)
{
if (i % 10 == 0)
printArray(vektorArray[i], n);
}
index that array with v. Looks like you got your variables crossed. Strongly recommend giving variables better, more descriptive names to help make this more obvious.
I don't know how I can parallel this loops because I have a lot of dependent variables and I am very confused
can you help and guide me?
the number one is :
for (int a = 0; a < sigmaLen; ++a) {
int f = freq[a];
if (f >= sumFreqLB)
if (updateRemainingDistances(s, a, pos))
if (prunePassed(pos + 1)) {
lmer[pos] = a;
enumerateStrings(pos + 1, sumFreqLB - f);
}
}
The second one is :
void preprocessLowerBounds() {
int i = stackSz - 1;
int pairOffset = (i * (i - 1)) >> 1;
for (int k = L; k; --k) {
int *dsn = dist[k] + pairOffset;
int *ds = dist[k - 1] + pairOffset;
int *s = colS[k - 1];
char ci = s[i];
for (int j = 0; j < i; ++j) {
char cj = s[j];
*ds++ = (*dsn++) + (ci != cj);
}
}
Really another one is :
void enumerateSubStrings(int rowNumber, int remainQTolerance) {
int nItems = rowSize[rowNumber][stackSz];
if (shouldGenerateNeighborhood(rowNumber, nItems)) {
bruteForceIt(rowNumber, nItems);
} else {
indexType *row = rowItem[rowNumber];
for (int j = 0; j < nItems; ++j) {
indexType ind = row[j];
addString(lmers + ind);
preprocessLowerBounds();
uint threshold = maxLB[stackSz] - addMaxFreq();
if (hasSolution(0, threshold)) {
if (getValid<hasPreprocessedPairs, useQ>(rowNumber + 1,
(stackSz <= 2 ? n : smallN), threshold + LminusD,
ind, remainQTolerance)) {
enumerateSubStrings<hasPreprocessedPairs, useQ>(
rowNumber + 1, remainQTolerance);
}
}
removeLastString();
}
}
void addString(const char *t) {
int *mf = colMf[stackSz + 1];
for (int j = 0; j < L; ++j) {
int c = t[j];
colS[j][stackSz] = c;
mf[j] = colMaxFreq[j] + (colMaxFreq[j] == colFreq[j][c]++);
}
colMaxFreq = mf;
++stackSz;
}
void preprocessLowerBounds() {
int i = stackSz - 1;
int pairOffset = (i * (i - 1)) >> 1;
for (int k = L; k; --k) {
int *dsn = dist[k] + pairOffset;
int *ds = dist[k - 1] + pairOffset;
int *s = colS[k - 1];
char ci = s[i];
for (int j = 0; j < i; ++j) {
char cj = s[j];
*ds++ = (*dsn++) + (ci != cj);
}
}
}
void removeLastString() {
--stackSz;
for (int j = 0; j < L; ++j)
--colFreq[j][colS[j][stackSz]];
colMaxFreq = colMf[stackSz];
}
Ok, For OpenMP to parallelize a loop in your basically follow these two rules, the first never write in the same memory location from different threads and second rule never depend on the reading of a memory area that may modified another thread, Now in the first loop you just change the lmer variable and other operations are read-only variables that I assume are not changing at the same time from another part of your code, so the first loop would be as follows:
#pragma omp for private(s,a,pos) //According to my intuition these variables are global or belong to a class, so you must convert private to each thread, on the other hand sumFreqLB and freq not included because only these reading
for (int a = 0; a < sigmaLen; ++a) {
int f = freq[a];
if (f >= sumFreqLB)
if (updateRemainingDistances(s, a, pos))
if (prunePassed(pos + 1)) {
#pragma omp critical //Only one thread at a time can enter otherwise you will fail at runtime
{
lmer[pos] = a;
}
enumerateStrings(pos + 1, sumFreqLB - f);
}
}
In the second loop i could not understand how you're using the for, but you have no problems because you use only reads and only modified the thread local variables.
You must make sure that the functions updateRemainingDistances, prunePassed and enumerateStrings do not use static or global variables within.
In the following function you use most only read operations which can be done from multiple threads (if any thread modifying these variables) and write in local memory positions so just change the shape of the FOR for OpenMP can recognize that FOR.
void preprocessLowerBounds() {
int i = stackSz - 1;
int pairOffset = (i * (i - 1)) >> 1;
#pragma omp for
for (int var=0; var<=k-L; var++){
int newK=k-var;//This will cover the initial range and in the same order
int *dsn = dist[newK] + pairOffset;
int *ds = dist[newK - 1] + pairOffset;
int *s = colS[newK - 1];
char ci = s[i];
for (int j = 0; j < i; ++j) {
char cj = s[j];
*ds++ = (*dsn++) + (ci != cj);
}
}
In the last function you use many functions for which I do not know the source code and thus can not know if they are looking for parallelizable example below the following examples are wrong:
std::vector myVector;
void notParalelizable_1(int i){
miVector.push_back(i);
}
void notParalelizable_2(int i){
static int A=0;
A=A+i;
}
int varGlobal=0;
void notParalelizable_3(int i){
varGlobal=varGlobal+i;
}
void oneFunctionParalelizable(int i)
{
int B=i;
}
int main()
{
#pragma omp for
for(int i=0;i<10;i++)
{
notParalelizable_1(i);//Error because myVector is modified simultaneously from multiple threads, The error here is that myVector not store the values in ascending order as this necessarily being accesing by multiple threads, this more complex functions can generate erroneous results or even errors in run time.
}
#pragma omp for
for(int i=0;i<10;i++)
{
notParalelizable_2(i);//Error because A is modified simultaneously from multiple threads
}
#pragma omp for
for(int i=0;i<10;i++)
{
notParalelizable_3(i);//Error because varGlobal is modified simultaneously from multiple threads
}
#pragma omp for
for(int i=0;i<10;i++)
{
oneFunctionParalelizable(i);//no problem
}
//The following code is correct
int *vector=new int[10];
#pragma omp for
for(int i=0;i<10;i++)
{
vector[i]=i;//No problem because each thread writes to a different memory pocicion
}
//The following code is wrong
int k=2;
#pragma omp for
for(int i=0;i<10;i++)
{
k=k+i; //The result of the k variable at the end will be wrong as it is modified from different threads
}
return 0;
}
I have a C++ program that sums numbers from 0 to n, using t threads. N and T are passed as command line args. I am using a for loop that creates the pthreads and a second for loop that rejoins the main to them. The program executes fine when I use less than 11 or 12 threads. For example, on input 100 10, it returns 5050. When I use more than 11-12 threads, it causes a segmentation fault and crashes. I cant seem to figure out why. There are some lines in my code I was using for debugging, such as printing to the prompt, etc. Any tips are appreciated!
int n = 0;
int t = 0;
unsigned long gsum = 0;
pthread_mutex_t mutexsum;
void *sum(void *Index)
{
int index = (int)(int *) Index;
int threadSum = 0;
int k;
int lowerBound, upperBound; //used to find range of numbers to sum
//printf("I am here: %d \n",index);
if (index == t - 1) {
lowerBound = (n/t)*(t-1);
upperBound = n;
} else {
lowerBound = (n/t)*index;
upperBound = (n/t)*(index+1)-1;
}
for (k = lowerBound; k < upperBound + 1; k++) {
threadSum = threadSum + k;
}
// Critical Section
pthread_mutex_lock(&mutexsum);
gsum = gsum + threadSum;
pthread_mutex_unlock(&mutexsum);
pthread_exit((void*) 0);
}
int main(int argc, char* argv[]){
int i, k, j;
pthread_t sumThreads [t];
for(i = 1; i < argc; i++) {
if(i == 1)
n = atoi(argv[i]);
if(i == 2)
t = atoi(argv[i]);
}
if (n < 0 || t <= 0 || argc != 3) {
printf("Invalid or missing parameters! \n");
exit(0);
}
for (k = 0; k < t; k++) {
int nt = -1;
nt = pthread_create(&sumThreads[k], NULL, sum, (void*)k);
printf("%d \n", nt);
}
for (j = 0; j < t; j++) {
int rj = -1;
rj = pthread_join (sumThreads[j], NULL);
printf("%d \n", rj);
}
printf("Total Sum: %lu \n",gsum);
return 0;
You have initialized t to be zero at the top of your program, so this line:
pthread_t sumThreads [t];
is not allocating an array large enough to hold the thread identifiers. Thus, you have buffer overrun when storing the identifiers, and your are reading past the buffer in your thread_join loop.
You are using a feature called variable length array (or VLA) which became part of the C language in the 1999 revision to the standard. C++ has not adopted VLA, so you are using a compiler extension. If you want your code to be compliant with C++, you should use a vector instead.
std::vector<pthread_t> sumThreads;
// ...after t gets initialized
sumThreads.resize(t);
In c/c++ this type of code does not work:
int i=10:
int arr[i];
Avoid doing this. If this type of code was valid we would no longer need malloc..
This is exactly what you are trying to achieve.
I am getting stuck on heapSort. I have some code but I think its pretty wrong since I'm having hard time compiling it. Any suggestions? Heap sort should be fairly easy to implement but I have bunch of syntax errors. Here's my code:
/* Framework for Heap Sort
* CS333 Spring 2011
*
*/
#include <stdio.h>
#define MAX_SIZE 1000000
int data[MAX_SIZE];
int n;
int j;
int parent(int j) {
if(j==1)
return 0;
if(j%2==0)
return ( (j / 2)-1);
else
return ( (j / 2));
}
int left(int j) {
return (2 * j) + 1;
}
int right(int j) {
return (2 * j) + 2;
}
void heapify(int data[], int j) {
int l = left(j), great;
int r = right(j);
if ( (data[l] > data[j]) && (l < sizeof(data))) {
great = l;
}
else {
great = j;
}
if ( (data[r] > data[great]) && (r < sizeof(data))) {
great = r;
}
if (great != j) {
int temp = data[j];
data[j] = data[great];
data[great] = temp;
heapify(data, great);
}
}
int BuildMaxHeap(int data[]) {
for (int j = (sizeof(data) - 1) / 2; j >= 0; j--) {
heapify(data, j);
return data;
}
}
void HeapSort(int data[]) {
BuildMaxHeap(data);
for (int j = sizeof(data); j > 0; j--) {
int temp = data[0];
data[0] = data[data.sizeof() - 1];
data[sizeof(data) - 1] = temp;
sizeof(data) = sizeof(data) - 1;
heapify(data, 0);
}
}
int main()
{
int i;
/* Read in the data */
n = 0;
while (scanf("%d", &data[n]) == 1)
++n;
/* Sort the numbers low to high */
HeapSort(data);
/* Print out the data */
for (i = 0; i < n; ++i)
printf("%d", data[i]);
}
Most of your problems seem to be in your HeapSort routine:
void HeapSort(int data[]) {
BuildMaxHeap(data);
for (int j = sizeof(data); j > 0; j--) {
When you pass an array to a function like this, what the function receives is actually a pointer. Using sizeof on that pointer will not tell you about the size of the data pointed to by the pointer -- it'll just tell you how many bytes the pointer itself occupies (typically 4). You probably want to pass the array size as a parameter:
void HeapSort(int *data, size_t data_size) {
and throughout the rest of the routine, you'll refer to data_size, not sizeof(data).
int temp = data[0];
data[0] = data[data.sizeof() - 1];
data[sizeof(data) - 1] = temp;
sizeof(data) = sizeof(data) - 1;
sizeof(whatever) is also essentially a constant, not a variable; you can't use it as the target of an assignment (but, again, using data_size as suggested above will let you do the assignment).